Extended component class names are identical to source since 2.4.0
See original GitHub issueI’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
- Create a component with a display name
- Create another component by
.extend
ing the first one - Reference the original component in a css selector and apply specific rules
- Reference the extended component in a subsequent selector and apply different rules
- 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 .extend
ed 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:
- Created 6 years ago
- Comments:10 (4 by maintainers)
Seems like this will be addressed by the deprecation / removal of
.extend
https://github.com/styled-components/styled-components/issues/1546I 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
andwithComponent
would solve the issue? After all it’s as easy (hard?) to check if they are being used as thestyled
export.