Skip to content
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

Merged
merged 7 commits into from
Jul 30, 2017
Merged

Add .extend and .withComponent deterministic ID generation #1044

merged 7 commits into from
Jul 30, 2017

Conversation

gregberge
Copy link
Contributor

Will fix #1031

I added a test with the new behaviour. This should fix server-side rendering issues with .extend and .withComponent.

@@ -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`', () => {
Copy link
Member

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 :)

const newComponentId =
previousComponentId &&
`${previousComponentId}-${ComponentStyle.generateName(
newRules.join(''),
Copy link
Member

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

Copy link
Contributor Author

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?

@gregberge
Copy link
Contributor Author

@philpl I modified the .extend, I wasn't taking extended rules. Making a .join('') is not a problem, you can see that it work in test. But I can also skip functions or replace it by a string "FUNC" if you prefer.

@gregberge
Copy link
Contributor Author

@philpl I made changes to support function interpolations

@kitten
Copy link
Member

kitten commented Jul 28, 2017

@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

rules: newRules,
ParentComponent: StyledComponent,
}

return constructWithOptions(createStyledComponent, target, newOptions)
const createWithHash = (tag, opts, css) => {
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@neoziro In this case we might want to think about a new option instead. Something like parentId which just passes down the old componentId. Then we let componentId be undefined and inside the StyledComponent factory we pass the parentId into generateId and prepend it to the new id.

cc @geelen

Copy link
Contributor Author

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?

Copy link
Member

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

Copy link
Contributor Author

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

@gregberge
Copy link
Contributor Author

@philpl done

@@ -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
Copy link
Member

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 😅

Copy link
Contributor Author

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)}`
Copy link
Member

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?

Copy link
Contributor Author

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.

@kitten
Copy link
Member

kitten commented Jul 29, 2017

@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 😄

@gregberge
Copy link
Contributor Author

@philpl ready to be merged

@kitten kitten merged commit ccd293b into styled-components:master Jul 30, 2017
@kitten
Copy link
Member

kitten commented Jul 30, 2017

Awesome! 🎉

@gregberge gregberge deleted the deterministic-id-generation branch July 30, 2017 19:05
@mxstbr
Copy link
Member

mxstbr commented Jul 31, 2017

Yay! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add .extend and .withComponent deterministic ID generation
3 participants