Skip to content

Fix defaultProps/props theme theming#253

Merged
mxstbr merged 11 commits intostyled-components:masterfrom
michalkvasnicak:fix/default-props-rerender
Nov 26, 2016
Merged

Fix defaultProps/props theme theming#253
mxstbr merged 11 commits intostyled-components:masterfrom
michalkvasnicak:fix/default-props-rerender

Conversation

@michalkvasnicak
Copy link
Copy Markdown
Member

@michalkvasnicak michalkvasnicak commented Nov 24, 2016

Fixes #252
Fixes #247

@mxstbr-bot
Copy link
Copy Markdown

mxstbr-bot commented Nov 24, 2016

3 Warnings
⚠️ changes to ThemeProvider.js might be semver major changes
⚠️ changes to StyledComponent.js might be semver major changes
⚠️ changes to StyledNativeComponent.js might be semver major changes

Generated by 🚫 danger

Copy link
Copy Markdown
Member

@mxstbr mxstbr left a comment

Choose a reason for hiding this comment

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

Amazing! Apart from the bot comments (add a CHANGELOG entry) I left a few comments inline, but other than those nitpicks this looks great! Thanks!

}

// compare if there is any change
if (JSON.stringify(nextProps.theme) === JSON.stringify(this.state.theme)) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this be a deep equality check instead of JSON.stringify? What's the difference?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@mxstbr I didn't want to install new dependency just because of this. But I am wondering if deep equality check is necessary. What do you think?

Isn't === enough?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since the main difference between a deep equality check and the JSON.stringify method (which I find very smart btw, have never heard of that before) is that the deep equality check doesn't care about the ordering of the elements. (see here for more info)

How big is the a dependency that can do deep equality?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@mxstbr I don't know if there is need to do other equality check than ===. Because if we pass the same theme to generateAndInjectStyles() we should get the same result right?

I am looking on this https://github.com/substack/node-deep-equal.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah I guess you're right. Let's bail out earlier if it's the exact same object, but otherwise do a stringify comparison:

if (nextProps.theme === this.state.theme || JSON.stringify(nextProps.theme) === JSON.stringify(this.state.theme)) {

This way we don't stringify if it's exact same object, which saves quite a bit of time, but then just stringify and compare deeply if they aren't.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah this solution is better than introducing new dependency :)

return
}

const { theme } = nextProps
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's move this destructure to the function argument and use the theme variable throughout componentWillReceiveProps({ theme }).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done. I hope flowtype is correct.

import jsdom from 'mocha-jsdom';
import React from 'react'
import { render } from 'enzyme'
import { mount as render } from 'enzyme'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do we rename this to render? That's a separate mode, let's rename all instances of render to mount instead, otherwise this could be confusing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah I forgot to refactor this :)

nextProps
)
this.setState({ generatedClassName })
componentWillReceiveProps({ theme }: { theme: ?{ [key: string]: mixed } }) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this should be ({ theme }: { theme?: Object })? I'm not a flow type expert though, so maybe I'm wrong. @styled-components/typers how do we do this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@mxstbr This annotation is the same as Theme in ThemeProvider. I can export Theme type from ThemeProvider component and use it here. Then it would be { theme: ?Theme }.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@mxstbr Theme type is now exported from ThemeProvider and used in StyledComponent and StyleNativeComponent. What do you think?

@mxstbr
Copy link
Copy Markdown
Member

mxstbr commented Nov 24, 2016

Oh sorry, I just realized that this will probably increase our rendering time since we're now doing a full jsdom render for every test. Do you mind adding a describe('jsdom', () => { jsdom() }) section in which we can put all the tests that require a full DOM render (i.e. mount), but use enyzmes render for all the original ones? That should speed it up quite a bit I think.

Sorry for the troubles, thanks!

@michalkvasnicak
Copy link
Copy Markdown
Member Author

@mxstbr done 😉

@michalkvasnicak
Copy link
Copy Markdown
Member Author

michalkvasnicak commented Nov 25, 2016

@mxstbr Do not merge this yet, there is bug in componentWillReceiveProps. We can't bail out at all because it will not react to props change so for example if you have a style that is using props to calculate something, then it won't propagate changes at all.

@michalkvasnicak
Copy link
Copy Markdown
Member Author

@mxstbr ok fixed

@mxstbr
Copy link
Copy Markdown
Member

mxstbr commented Nov 26, 2016

Amazing work, thanks so much! Shipping a new version with these changes very soon!

@mxstbr mxstbr merged commit cd159c5 into styled-components:master Nov 26, 2016
This was referenced Nov 26, 2016
@michalkvasnicak michalkvasnicak deleted the fix/default-props-rerender branch November 27, 2016 10:24
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.

3 participants