Skip to content
This repository has been archived by the owner on Dec 13, 2018. It is now read-only.

Fixed nested themes not being republished on outer theme changes #363

Merged
merged 1 commit into from
Dec 22, 2017

Conversation

Andarist
Copy link
Contributor

@Andarist Andarist commented Dec 21, 2017

What:

This fixes a bug when having nested ThemeProviders and updating outer theme the change is not reaching the StyledComponent

<ThemeProvider theme={{}}>
	<ThemeProvider theme={{}}>
		<StyledComponent>
	</ThemeProvider>
</ThemeProvider>

Why:

This is a bug fix.

How:
Using publish in the nested ThemeProviders subscriptions.

Checklist:

  • Tests
  • Code complete

Repro provided by @mitchellhamilton - https://codesandbox.io/s/6j42qx5z23

@codecov-io
Copy link

codecov-io commented Dec 21, 2017

Codecov Report

Merging #363 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff          @@
##           master   #363   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          10     10           
  Lines         178    179    +1     
  Branches       50     50           
=====================================
+ Hits          178    179    +1
Impacted Files Coverage Δ
src/theme-provider.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update cb6de3a...a904c67. Read the comment docs.

@Andarist Andarist force-pushed the fix/nested-theme-providers branch from f96a56a to a904c67 Compare December 21, 2017 11:44
Copy link
Contributor

@kentcdodds kentcdodds left a comment

Choose a reason for hiding this comment

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

This looks fine (and awesome, thanks!), but I'm least comfortable with the theme code in this project. I didn't develop it myself, I rarely use it, and I'm not certain I understand all the use cases. So I'd really like someone who uses glamorous's ThemeProvider to give this a review as well. Thanks!

@@ -53,13 +58,12 @@ class ThemeProvider extends React.Component {
// set broadcast state by merging outer theme with own
if (this.context[CHANNEL]) {
this.setOuterTheme(this.context[CHANNEL].getState())
this.broadcast.setState(this.getTheme())
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you explain why this was removed? It seems unrelated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

publishTheme method is doing a setState and setOuterTheme uses now publishTheme under the hood

Copy link
Collaborator

@paulmolluzzo paulmolluzzo Dec 21, 2017

Choose a reason for hiding this comment

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

I think this is the real fix, and publishTheme is only incidentally changed.

This line was setting the state with no argument, which defaults to the props.theme here

const theme = passedTheme || this.props.theme
, meaning it's not setting the theme to the next theme it's just resetting it to the theme it already has.

A lot of the theming work was done by @vesparny, so if I'm wrong hopefully he can correct me. 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this part of defaulting to this.props.theme is a making a control flow a little bit iffy but I left this part untouched. Personally I would prefer explicit arguments, so that publishTheme would always have to receive getTheme's result as argument which in turn would always be called with this.props.theme if necessary.

Also I've noticed a different small issue too - broadcast is initialized as:

broadcast = brcast(this.props.theme)

but that gives it untrue initialState in case of nested ThemeProvider. I think creation of the broadcast should be delayed.

Copy link
Collaborator

Choose a reason for hiding this comment

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

but that gives it untrue initialState in case of nested ThemeProvider. I think creation of the broadcast should be delayed.

I'm pretty sure I follow, but to be clear, are you suggesting moving it to something like componentWillMount? With this PR, the theme that was (possibly) merged with the outer theme is now going to be set properly inside componentWillMount(), so that untrue initial state won't really ever be in effect.

Did I follow your point correctly? If not any clarification would be great. 🙌

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that was exactly my point :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Cool, thanks! It makes sense to me. Maybe you want to do that as a follow-up PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure thing, would prefer to create it once we settle on this one to avoid potential conflicts

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the discussion here!

@Andarist
Copy link
Contributor Author

@kentcdodds do u have any other reviewer in mind? The chane is pretty straightforward and the codebase is tested so it shouldnt break anything ;)

}
}

componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
this.broadcast.setState(this.getTheme(nextProps.theme))
this.publishTheme(nextProps.theme)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Pardon my ignorance, but how has this made an effectual change? publishTheme is calling broadcast.setState(this.getTheme(nextProps.theme)) which is was was here before. It's only been moved to a separate method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh, this part is actually not a fix of any sorts, i just have extracted it to separate method so it would be easier to reuse it in setOuterTheme

Copy link
Collaborator

Choose a reason for hiding this comment

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

OK, thanks for clarifying.

Copy link
Collaborator

@paulmolluzzo paulmolluzzo left a comment

Choose a reason for hiding this comment

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

LGTM.

Frankly, I haven't used nested ThemeProviders that much so if @vesparny or @goodmind have time to review that'd be great.

Whoops, forgot to say thank you @Andarist!

Copy link
Contributor

@kentcdodds kentcdodds left a comment

Choose a reason for hiding this comment

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

Super! Thank you for your help!

@@ -53,13 +58,12 @@ class ThemeProvider extends React.Component {
// set broadcast state by merging outer theme with own
if (this.context[CHANNEL]) {
this.setOuterTheme(this.context[CHANNEL].getState())
this.broadcast.setState(this.getTheme())
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the discussion here!

@kentcdodds kentcdodds merged commit 8cd90bd into paypal:master Dec 22, 2017
@Andarist Andarist deleted the fix/nested-theme-providers branch December 22, 2017 11:03
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants