Redux 应用程序中每个 reducer 调用深度复制状态的缺点是什么? [英] What are the cons of deep copying state on each reducer call in Redux application?

查看:29
本文介绍了Redux 应用程序中每个 reducer 调用深度复制状态的缺点是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每次调用 reducer 函数时,在 Redux 应用程序中的 appReducer 上对 state 进行深度复制是否有任何副作用?

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?

我问是因为不可变更新模式 Redux 的文档指出,要更新状态上的嵌套对象,您应该浅复制嵌套属性并更新它.

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.

这里是一些伪代码示例

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;
  }
}

总是深复制状态然后返回它的方法有什么不好?我还没有看到这样做,所以我假设它有问题.如果 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?

推荐答案

深度复制状态将导致所有 jsx 被重新创建,并且 React 必须比较整个虚拟 dom 并可能重新渲染 DOM.重新渲染 DOM 是您的网络应用中最昂贵的操作之一,当您可以防止这种情况发生时,您应该这样做.

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.

当一个动作被分派并且reducer返回一个新状态时,所有传递给useState的回调都会被调用,当它们返回一个与上次不同的值时,组件将重新创建jsx.然后 React 会将该 jsx 与上次进行比较,并可能重新绘制 DOM.

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} />;
});

如果您在每个分派的操作上重新创建整个状态(深拷贝),那么该代码中的任何优化都不会做任何事情.更糟糕的是,item 改变了,所以 remove 被重新创建,这意味着 Component 将在 DOM 中重新呈现,因为处理函数甚至改变了尽管 item 可能实际上并没有改变它只是因为你深度复制了状态.

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.

这篇关于Redux 应用程序中每个 reducer 调用深度复制状态的缺点是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆