-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add .extend and .withComponent deterministic ID generation #1044
Add .extend and .withComponent deterministic ID generation #1044
Conversation
src/test/expanded-api.test.js
Outdated
@@ -62,6 +62,19 @@ describe('expanded api', () => { | |||
expect(Comp2.styledComponentId).toBe('Comp2-OMGLOL') | |||
expect(shallow(<Comp2 />).prop('className')).toMatch(/Comp2-OMGLOL/) | |||
}) | |||
|
|||
it('should work with `.extend` and `.withComponent`', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we separate the .extend
from the .withComponent
tests? That should make these tests a bit shorter :)
src/models/StyledComponent.js
Outdated
const newComponentId = | ||
previousComponentId && | ||
`${previousComponentId}-${ComponentStyle.generateName( | ||
newRules.join(''), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These rules might contain some interpolations. I'm not sure whether it's a good idea to blindly join them 🤔 cc @geelen
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@philpl what do you suggest?
@philpl I modified the |
@philpl I made changes to support function interpolations |
@neoziro That is looking fine. The only thing I'm concerned about is performance in this case 😉 I'll take a look later and see whether it's sufficient |
src/models/StyledComponent.js
Outdated
rules: newRules, | ||
ParentComponent: StyledComponent, | ||
} | ||
|
||
return constructWithOptions(createStyledComponent, target, newOptions) | ||
const createWithHash = (tag, opts, css) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not quite looking optimal, in terms of V8 preoptimisation. It will probably deopt this function, since it's created on every call. Any reason why you were unhappy with your previous implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@philpl previously the hash was not built with the rules of .extend
. It was built with the rule of the original component. That is not what we want. This is the only way to do it. Also about performances, I think we can do this only if we have a component id.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@philpl I don't know the entire codebase in mind, I let you decide what is the best! Should I introduce a parentId
concept or I let you do it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@neoziro Since you're already fully at it and getting your hands dirty, I can guide you to what I mean 😄
Here we could just pass in the componentId
as a parentComponentId
: https://github.com/styled-components/styled-components/blob/master/src/models/StyledComponent.js#L229
Then it'd eventually arrive back in the factory here: https://github.com/styled-components/styled-components/blob/master/src/models/StyledComponent.js#L178
There we can add a new argument to generateId
:
const {
componentId = generateId(options.displayName, options.parentComponentId)
} = options
Then inside generateId
you can concatenate this with displayName
to make the new component id "more unique" i.e. different from the parent's one: https://github.com/styled-components/styled-components/blob/master/src/models/StyledComponent.js#L26
One thing we also need to do (probably not in this PR) is passing in the runtime inferred (default) displayName
into generateId
as well instead of just options.displayName
: https://github.com/styled-components/styled-components/blob/master/src/models/StyledComponent.js#L177
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@philpl I understood everything, will do it soon
@philpl done |
src/models/StyledComponent.js
Outdated
@@ -32,7 +32,8 @@ export default (ComponentStyle: Function, constructWithOptions: Function) => { | |||
identifiers[displayName] = nr | |||
|
|||
const hash = ComponentStyle.generateName(displayName + nr) | |||
return `${displayName}-${hash}` | |||
const componentId = `${displayName}-${hash}` | |||
return parentComponentId ? `${parentComponentId}-${componentId}` : componentId |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe parentComponentId !== undefined
? Sorry for the nit, but we have an ongoing perf pr and it'd be good to keep things optimised 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
const newComponentId = | ||
previousComponentId && | ||
`${previousComponentId}-${isTag(tag) ? tag : getComponentName(tag)}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should extract this logic into a small function at the top of this file, now that it's used twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not exactly the same, so I prefer to keep it separated.
@neoziro This is looking perfect! 🎉 I added two small nits. I'll test this and see if it fixes the SSR issues, but I don't see why it wouldn't 😄 |
@philpl ready to be merged |
Awesome! 🎉 |
Yay! 🎉 |
Will fix #1031
I added a test with the new behaviour. This should fix server-side rendering issues with
.extend
and.withComponent
.