Reactjs和Redux更新状态是可变的还是不可变的?

Reactjs和Redux更新状态是可变的还是不可变的?,reactjs,redux,Reactjs,Redux,我对Reactjs和Redux非常陌生,任何人都可以解释Reactjs/Redux中什么是可变的和不可变的 我正在使用Redux来更新状态,并使用它来控制我的UI布局,但是我发现下面的一种方法不起作用,尽管这两种方法都在更新对象 我有一个存储对象,如下所示: const initialAppState = { showSideBar: false, showSwitcher: false, showRightPane: false,

我对Reactjs和Redux非常陌生,任何人都可以解释Reactjs/Redux中什么是可变的和不可变的

我正在使用Redux来更新状态,并使用它来控制我的UI布局,但是我发现下面的一种方法不起作用,尽管这两种方法都在更新对象

我有一个存储对象,如下所示:

const initialAppState = {
          showSideBar: false,
          showSwitcher: false,
          showRightPane: false,
          menu: [
                {
                  name: "Home",
                  redirect: "/",
                },
                {
                  name: "About",
                  redirect: "/about",
                  expanded: false,
                  childs: [{
                      name: "Child one", 
                      redirect: "/Child"
                  }]
                },
            ]
        }
除此之外,我还有一个Pane.js和Menu.js来呈现我的菜单列表

Pane.js

const LeftPane = (props) => {
    return <List>
          {links.map((o, index) => {
            return <Menus key={o.name} props={o} index={index} />
          })}
    </List>
}
const Menus = ({ props, index, onToggleSubMenu }) => {
   return <ListItem> ...
}
另一方面,如果我从下面的代码中更新扩展值,它就会工作

const AppReducer = (state = initialAppState, action) => {
   state.menu[action.index] = Object.assign({}, state.menu[action.index], {
      expanded: !state.menu[action.index].expanded,
    });
    return {...state, menu: state.menu}
}

这两者有什么不同?更新状态的正确方法是什么?为什么我们应该使用Object.assign或spread(…)操作符来更新状态?我已经阅读了,上面的工作代码更像是链接中提到的常见错误。

程序中,有两件事你应该做得不同

  • Map函数返回一个新数组,并且不改变原始数组,因此不需要在那里进行析构函数
  • 在map函数中,您拥有对对象m的引用,并且您正在通过将
    m.expanded
    更改为
    来改变m!m、 已展开
    。这是您实际应该返回新对象的地方
  • 您应该按照以下方式编写
    appeducer

    const AppReducer=(state=initialAppState,action)=>{
    返回{
    ……国家,
    //使用map时无需销毁,map始终返回一个新数组
    菜单:state.menu.map((m,i)=>{
    if(i==action.index){
    //返回一个新对象,复制所有属性,并切换展开的值
    返回{
    M
    扩展:!m.expanded;
    }
    }
    //返回原始对象,因为未进行任何更改
    返回m;
    }),
    };
    };
    

    至于spread操作符和
    Object.assign
    之间的区别,根据,一个是另一个的语法糖,即
    {…a}
    是编写
    Object.assign({},a)更简单的方法

    在您的
    评价者中,有两件事您应该做得不同

  • Map函数返回一个新数组,并且不改变原始数组,因此不需要在那里进行析构函数
  • 在map函数中,您拥有对对象m的引用,并且您正在通过将
    m.expanded
    更改为
    来改变m!m、 已展开
    。这是您实际应该返回新对象的地方
  • 您应该按照以下方式编写
    appeducer

    const AppReducer=(state=initialAppState,action)=>{
    返回{
    ……国家,
    //使用map时无需销毁,map始终返回一个新数组
    菜单:state.menu.map((m,i)=>{
    if(i==action.index){
    //返回一个新对象,复制所有属性,并切换展开的值
    返回{
    M
    扩展:!m.expanded;
    }
    }
    //返回原始对象,因为未进行任何更改
    返回m;
    }),
    };
    };
    

    至于spread操作符和
    Object.assign
    之间的区别,根据,一个是另一个的语法糖,即
    {…a}
    是编写
    Object.assign({},a)更简单的方法

    应为:
    展开:!m、 扩展的
    您的代码可以工作,但是
    状态。菜单[action.index]
    已作为
    m
    My bad HMR提供,谢谢您的更新。我将更新答案。应该是:
    扩展:!m、 扩展的
    您的代码可以工作,但是
    状态。菜单[action.index]
    已作为
    m
    My bad HMR提供,谢谢您的更新。我会更新答案。
    const AppReducer = (state = initialAppState, action) => {
       state.menu[action.index] = Object.assign({}, state.menu[action.index], {
          expanded: !state.menu[action.index].expanded,
        });
        return {...state, menu: state.menu}
    }