Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/464.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么可以';使用React useReducer时返回上一状态的映射_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript 为什么可以';使用React useReducer时返回上一状态的映射

Javascript 为什么可以';使用React useReducer时返回上一状态的映射,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我创建了一个简单的应用程序来说明: 破碎的: 工作: 在应用程序中,我使用了一个reducer来保持复选框的状态和数组,以及一个allChecked布尔值 { checks: [ { id: 1, selected: false }, { id: 2, selected: false }, { id: 3, selected: false }, ], allChecked: false, } 我有一个减缩器,当一个复选框被更改时,应该在复选框数组中标识该

我创建了一个简单的应用程序来说明:

  • 破碎的:
  • 工作:
在应用程序中,我使用了一个reducer来保持复选框的状态和数组,以及一个allChecked布尔值

{
  checks: [
    { id: 1, selected: false },
    { id: 2, selected: false },
    { id: 3, selected: false },
  ],
  allChecked: false,
}
我有一个减缩器,当一个复选框被更改时,应该在复选框数组中标识该复选框,并将值设置为与原来相反的值

  case 'SELECT_CHECK': {
    return {
      checks: state.checks.map((check, i) => {
        if (action.id === check.id) {
          check.selected = !check.selected;
        }
        return check;
      }),
      allChecked: state.checks.reduce((acc, check) => {
        if (!acc) return false;
        return check.selected;
      }, true),
    };
  }
单击每个复选框时,映射应运行并返回
check.selected=!选中。已选定
。将此注销表明它按预期工作,但重新调整此状态不会改变状态。复选框永远不会被选中

我找到了一个解决方法,它通过分派操作传递复选框的状态,并显式地将复选框的新状态设置为
e.target.checked

  //checkbox jsx
  <input
    type='checkbox'
    checked={check.selected}
    onChange={(e) => {
      dispatch({ type: 'SELECT_CHECK', id: check.id, checked: e.target.checked });
    }}
  />
  //reducer case statement
  case 'SELECT_CHECK': {
    return {
      checks: state.checks.map((check, i) => {
        if (action.id === check.id) {
          check.selected = action.checked;
        }
        return check;
      }),
      allChecked: state.checks.reduce((acc, check) => {
        if (!acc) return false;
        return check.selected;
      }, true),
    };
  }
//复选框jsx
{
分派({type:'SELECT_CHECK',id:CHECK.id,checked:e.target.checked});
}}
/>
//减速器案例陈述
案例“选择检查”:{
返回{
检查:state.checks.map((检查,i)=>{
if(action.id==check.id){
check.selected=action.checked;
}
退货检查;
}),
allChecked:状态.检查.减少((acc,检查)=>{
如果(!acc)返回false;
返回检查。选中;
}是的,
};
}
虽然此函数起作用,但我想了解初始尝试不起作用的原因,以及是否有方法使此函数不通过
操作。选中的

下面是一个GIF以显示预期状态

当需要更新处于React状态的对象时,应始终使用新对象替换处于React状态的现有对象,而不是更改处于React状态的对象。这:

  checks: state.checks.map((check, i) => {
    if (action.id === check.id) {
      check.selected = !check.selected;
    }
    return check;
  }),
应该是

  checks: state.checks.map(check => (
    action.id === check.id ? ({ ...check, selected: !check.selected }) : check
  ))

创建一个新对象,使现有对象的所有属性都处于状态,但选择了反转的
属性除外

相比之下,你的

check.selected = !check.selected;

在不返回新对象的情况下更改对象,在这种情况下,如果处于上一状态的对象和处于新状态的对象是
==
,React可能会尝试完全跳过涉及该对象的重新渲染,因为它不会检测到状态差异。

您正在更改状态。千万不要这样做,谢谢@CertainPerformance!我想是的。地图上有一份州政府的副本。我还尝试了
[…state.checks]
以获取副本,但没有成功。有没有合适的方法可以在不通过
操作的情况下执行此操作。选中了
非常感谢!我不明白,通过返回
check
而不是
{…check}
我假设.map正在复制,这是一种变异状态。我还发现这有助于进一步解释:
check.selected = !check.selected;