问题
Are there any side effects of doing a deep copy of state
on the appReducer in a Redux application each time a reducer function is called?
I'm asking because the Immutable Update Pattern docs for Redux state that to update a nested object on state, you should shallow copy the nested property and update it.
I'm curious what the side effects would be for just doing a deep copy on state on every action call.
Here is some pseudo code for example
export default function appReducer(state = initialState, action){
let copiedState = JSON.parse(JSON.stringify(state))
switch(action){
case action.UPDATE_NESTED_PROPERTY:
copiedState.thing.anotherThing = somethingNew;
return copiedState;
case action.UPDATE_SOME_OTHER_NESTED_PROPERTY:
copiedState.differentThing.nestedProperty = "updated";
return copiedState;
default:
return state;
}
}
What is bad about the approach of always deep-copying state and then returning it? I haven't seen this done and so I am assuming there is something wrong with it. If state is a massive object, then I'm sure doing a deep copy each time could have issues with performance. But would this cause other issues?
回答1:
Deep copying state will cause all jsx to be re created and React having to compare the entire virtual dom and possibly re rendering the DOM. Re Rendering DOM is one of the most expensive operation of your web app and when you can prevent that from happening you should.
When an action is dispatched and the reducer returns a new state then all the callbacks passed to useState
are called and when they return a different value than last time the component will re create jsx. React will then compare that jsx with last time and possibly re paint the DOM.
Say I have a container like this:
const Container = React.memo(function Container({ id }) {
const dispatch = useDispatch();
//only if id changes will it re create the selector
const selectItem = React.useMemo(
() => createSelectItem(id),
[id]
);
const item = useSelector(selectItem);
//create remove function only when item has changed
const remove = React.useCallback(
//removeItem is an action creator
() => dispatch(removeItem(item)),
[item, dispatch]
);
//render component only when item changes
return <Component item={item} remove={remove} />;
});
If you recreate the entire state (deep copy) on every dispatched action then none of the optimisations in that code will do anything. What's even worse is that item
changed so remove
is re created and that means that Component
will be re rendered in DOM since the handler function changed even though item
may not actually have changed it only changed because you deep copied the state.
来源:https://stackoverflow.com/questions/66092530/what-are-the-cons-of-deep-copying-state-on-each-reducer-call-in-redux-applicatio