Reputation: 176
When a component is created this.state is defined. Then, after calling setState React somehow splits the old and new state into two objects. Using for example the hook shouldComponentUpdate we can diff these two states like so:
shouldComponentUpdate(nextProps, nextState) {
return (this.state.foo != nextState.foo);
}
I downloaded the React source from github and i found where these functions were called, but it quickly became too hard to keep track of what was going on. I never found where this split (or however they implemented this behavior) takes place. I did find that shallow comparisons was/could be used by React to diff the states, so i wonder if they simply clone the state object and then merge the updated values into one of them so that the two of them can be compared later. Is this correct? In such a case, how is nested structures handled? Or are they using a version of get/set and/or a version of Proxy API to catch the changes somehow?
Upvotes: 1
Views: 194
Reputation: 176
For future reference: I managed to find the location in the React source code where the new state deviates from the old state.
I used the latest master branch of the React Github repository (commit hash e7b255341b059b4e2a109847395d0d0ba2633999) for this.
Disclaimer, this is only my interpretation and i go mostly from memory. The magic happens in the file packages/react-reconciler/src/ReactUpdateQueue.new.js, in the function getStateFromUpdate. When invoking setState an Update object (update.tag = UpdateState) is created and added to an update queue (for asynch behavior). The tag is used in a switch-statement in this function for specific update logic. At the bottom of the case UpdateState we see that React clones the previous state and merges it with "partialState", which is the state object passed to the setState call. This cloning is done using:
// Merge the partial state and the previous state.
return Object.assign({}, prevState, partialState);
The new state is returned from this function and the previous state is still stored somewhere. They can now be used for later comparison. As a side note, ForceUpdate is also handled here which simply returns the previous state (which then according to the same logic becomes the new state).
Regarding the second part of my question, how nested structures are handled. Given this new-found knowledge, after some searching i found this question which answered that nicely.
Upvotes: 1
Reputation: 1961
In react JS using class concept for shouldComponentUpdate
, if we don't override it, Component
will always return true and PureComponent
implements a shallow comparison (Shallow compare works by checking if two values are equal in case of primitive types like string, numbers and in case of object it just checks the reference) on props and state and returns true if any props or states have changed.
In case we override shouldComponentUpdate, we will have previous props and previous state. There are already store in object class component. For next props and next state, i think:
setState
. It is be cloned from previous state and was added new change for that. So, reference of previous state and reference of next state will be always different.Upvotes: 0