Merge initial state from new components with current state - #39
Merge initial state from new components with current state#39robertknight wants to merge 1 commit into
Conversation
7b19f9f to
8758e42Compareghost
commented
Jan 25, 2016
If I'm reading this correctly, it would help the case where you add state to a previously stateless component and have to reload the page. That would be awesome :) I'm I correct in this understanding? |
robertknight
commented
Jan 26, 2016
Yes, indeed. See the tests for examples of exactly this. |
gaearon
commented
Jan 28, 2016
This is interesting! I'm a bit busy at the moment but I'll definitely come back to this. |
robertknight
commented
Jan 28, 2016
Thanks @Gearon , much appreciated. |
creeperyang
commented
Feb 2, 2016
It's just what I need. But maybe we don't need merge old state, just replace/overwrite? |
creeperyang
commented
Feb 3, 2016
@gaearon@robertknight I'm not sure am I right, but I'm confused about this issue/feature. First a demo/case with // beforeclassMyComponentextendsComponent{constructor(){super();this.state={title: 'Hi'};};render(){return<h1>{this.state.title}</h1>};}// then I rewrite/update the code toclassMyComponentextendsComponent{constructor(){super();this.state={title: 'Hello'};};render(){return<h1>{this.state.title}</h1>};}I just want the browser to show (updated to) So, is the feature I expected correct? |
ghost
commented
Feb 3, 2016
@creeperyang In the example you provided, I would expect title to remain equal to 'Hello'. If you were to update the component and add a property named 'description` with a value, I'd expect that to appear in the state object. Basically, any new properties that are added to the state object are merged. Existing properties will retain their current values. |
creeperyang
commented
Feb 4, 2016
@danmartinez101 I agree with you. And the problem is:
robertknight@8758e42#diff-b41c7eca2d25b7c593fb114f1d99ded4R9 with this line, the previous state property would have higher priority. |
robertknight
commented
Feb 4, 2016
@creeperyang Giving higher priority to the existing component state is what I intended to do and I think that is what @danmartinez101 meant to say, so that line of code is not wrong from my point of view. If higher priority was given to the new component's state, that would reset everything to its default values and defeat the point of Fundamentally, the only correct way to work out what the new state should be given the new code is to replay all the events which resulted in state changes - which is what Redux dev tools do. Merging the state is just intended to be a reasonable behavior given the lack of information about how the component got to its current state. |
creeperyang
commented
Feb 4, 2016
@robertknight Maybe you're right. But I track this issue here because I use As the demo above show, when I use react transfrom tool, and I change my code, I expect the state in browser sync with the code. From this point, I'm not wrong too. But the |
ghost
commented
Feb 4, 2016
Yea, I mixed up the values. woops |
When replacing a proxied component that has no state with one that does have state, renders and lifecycle methods that depend on the initial state will typically fail with 'this.state is null' errors. This addresses the issue by invoking getInitialState() on classic components or running the constructor for modern components and merging the resulting state with the existing state, with the existing state taking priority. Fixesgaearon#38
ba49d2b to
d30a62bComparerobertknight
commented
Mar 6, 2016
I've updated the PR to call componentWillMount and componentWillUnmount when merging state to try and deal with ES2015 constructors that set up subscriptions etc. |
gaearon
commented
Mar 6, 2016
Hmm. Now that I think of it I was wrong 😞 Sure, At this point we should either
(2) sounds OK to me, I guess. Sorry for wasting your time! Would you mind changing it back to the way it was? |
robertknight
commented
Mar 7, 2016
I've reverted the change to call componentWillMount, componentWillUnmount. This does show an inconsistency in React's lifecycle functions in that |
wkwiatek
commented
Mar 6, 2017
Is this PR still valid for |
robertknight
commented
Mar 17, 2017
I honestly don't know and I'm afraid I probably won't get a chance to look at it soon. Feel free to close this one out for the moment if you're trying to tidy up open PRs. |
This is an initial pass at coping with the case where new state fields are added to components from one version to the next.
The approach taken here is to get the initial state of the new version of the component, given its current props and merge that with the existing state of the component. If the result is not shallow-equal to the previous state, the proxy invokes
component.setState(mergedState).The downside of this approach is that this will not always get the state to match what it would have been given the state and props transitions that have occurred since the component was instantiated.
Fixes#38