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, } 我有一个减缩器,当一个复选框被更改时,应该在复选框数组中标识该
- 破碎的:
- 工作:
{
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;