-
Notifications
You must be signed in to change notification settings - Fork 50
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
Merge initial state from new components with current state #39
base: master
Are you sure you want to change the base?
Conversation
7b19f9f
to
8758e42
Compare
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? |
Yes, indeed. See the tests for examples of exactly this. |
This is interesting! I'm a bit busy at the moment but I'll definitely come back to this. |
Thanks @Gearon , much appreciated. |
It's just what I need. But maybe we don't need merge old state, just replace/overwrite? |
@gaearon @robertknight I'm not sure am I right, but I'm confused about this issue/feature. First a demo/case with // before
class MyComponent extends Component {
constructor() {
super();
this.state = { title: 'Hi' };
};
render() {
return <h1>{this.state.title}</h1>
};
}
// then I rewrite/update the code to
class MyComponent extends Component {
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? |
@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. |
@danmartinez101 I agree with you. And the problem is:
robertknight@8758e42#diff-b41c7eca2d25b7c593fb114f1d99ded4R9 with this line, the previous state property would have higher priority. |
@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. |
@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 |
Yea, I mixed up the values. woops |
8758e42
to
bea4403
Compare
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. Fixes gaearon#38
ba49d2b
to
d30a62b
Compare
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. |
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? |
d30a62b
to
6953869
Compare
I've reverted the change to call componentWillMount, componentWillUnmount. This does show an inconsistency in React's lifecycle functions in that |
Is this PR still valid for |
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