question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Extended component class names are identical to source since 2.4.0

See original GitHub issue

I’ve found a change in behavior in 2.4.0 regarding a use case which I have throughout my projects.

Version

styled-components: 2.4.0 babel-plugin-styled-components: 1.1.4

Reproduction

Here’s a bin with styled-components@2.1.0 showing the old behavior and an example use case: https://www.webpackbin.com/bins/-L21eW94UfVVgVMuHpFB

Here’s a bin with styled-components@2.4.0 showing the new behavior: https://www.webpackbin.com/bins/-L21fE4nVqxENjuFYlZg

This also happens when you have two entirely separate components which happen to share the same display name. That becomes especially tricky when using the Babel transform… it may not be ideal, but I also bet it’s not uncommon for users to define multiple const Button = styled.button\…` components at various parts of large applications.

A bin of that: https://www.webpackbin.com/bins/-L21qbcO5llu9TPJihao

Steps to reproduce

  1. Create a component with a display name
  2. Create another component by .extending the first one
  3. Reference the original component in a css selector and apply specific rules
  4. Reference the extended component in a subsequent selector and apply different rules
  5. Result: the original component matches the second selector

This behavior occurs whether the display name is provided using withConfig or via the Babel transform.

Expected Behavior

A variant of a styled-component which was created with .extend will receive a unique class name. When referenced as a parent in a css selector, that selector will not match the original component which was extended.

Actual Behavior

A variant of a styled-component which was created with .extend keeps the same class name as the original, and selectors for either component match both.

Notes

This behavior is the direct result of the new hashing introduced in 2.4.0, but I wasn’t sure if this was an intentional change or not, so I thought some discussion might be welcome before submitting a PR.

The biggest problem I can see with the new behavior going forward is that I believe it’s now impossible to differentiate between a source component and a component which was .extended from it using component selectors alone.

I’m also not aware of any way to tell that a component is extended during the hashing, so I’m guessing that may have to be added to generate unique but stable class names for extended components. Fixing for the extended case also doesn’t fix for the identical display name case. As much as I agree with the desire to have consistent hashing, I think it’s also good not to have to wonder whether your component’s name collides with another in your project or external libraries before you use it in a selector.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
a-typecommented, Feb 26, 2018

Seems like this will be addressed by the deprecation / removal of .extend https://github.com/styled-components/styled-components/issues/1546

0reactions
fatfiszcommented, Jan 16, 2018

I spotted this issue today too; either inlining the styles or using the styled(BaseComponent) wrapper works.

I was thinking about this a bit, and maybe having named exports extend and withComponent would solve the issue? After all it’s as easy (hard?) to check if they are being used as the styled export.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Deprecate .extend in favour of only styled(Component) #1546
The FAQ explains the difference between styled() and .extend. ... Extended component class names are identical to source since 2.4.0 #1402.
Read more >
Unable to load class AndroidComponentsExtension after ...
After upgrading, I get a build error: Unable to load class 'com.android.build.api.extension.AndroidComponentsExtension'. This is ...
Read more >
Releases - styled-components
After an epic amount of refactoring, I'm pleased to announce the first alpha of styled-components v6! Highlights: styled-components is now written in TypeScript ......
Read more >
API - Vue.js
Allows declaratively extending another component (could be either a plain options object or a constructor) without having to use Vue.extend . This is...
Read more >
SpringApplication (Spring Boot 3.0.1 API)
public class SpringApplication extends Object. Class that can be used to bootstrap and launch a Spring application from a Java main method.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found