问题
Redux requires that one always returns new state from reducers. For example, I have the following state:
let initialState = {
prop: 3,
internalReferenceProp: {a:3}
}
And the reducer that modifies internalReferenceProp
. This reducer can be implemented to change only state
object reference or both state
and internalProperty
:
function(state=initialState, action) {
// changing only state reference
let newState = Object.assign({}, state);
newState.internalReferenceProp.a = 7;
return newState;
// changing both state and internalReferenceProp reference
return Object.assign({}, state, {internalReferenceProp: {a:7}})
}
As I've been told first approach is not correct, so my question is what's the reasoning behind requirement to also change internal references? I understand that I should change state
reference because it allows for an easy comparison to detect whether state
changed, but why change internal references?
回答1:
The first one is clearly not correct because Object.assign
does a shallow copy, not a deep one.
// changing only state reference
let newState = Object.assign({}, state);
newState === state // false
newState.internalReferenceProp === state.internalReferenceProp // true
state.internalReferenceProp.a // 3
newState.internalReferenceProp.a = 7 // 7
state.internalReferenceProp.a // 7
You can see that this way, if we change something in newState
it gets changed in state
as well. This will make the change undetectable if a component is only interested in internalReferenceProp
. This is also called a "side-effect" and is a bad practice.
In short, if your input (state
in this case) changes in any way, it's called a side-effect and is wrong in redux.
Here's an example of why this is bad:
let data = getData(); // from redux
return (
<ChildComponent someProp={data.internalReferenceProp} />
);
If we use the version with side-effects, ChildComponent
will never re-render because its props didn't change. oldData.internalReferenceProp === newData.internalReferenceProp
.
来源:https://stackoverflow.com/questions/34516894/why-is-the-requirement-to-always-return-new-object-with-new-internal-references