在我staffReducer
,我试图签署工作人员正在工作。
我有一个案例如下:
const staffReducer = (state=[], action)=>{
switch(action.type){
case "SET_WORKING":
let staff = state.find(x=> x.id == action.id);
if (!staff.working) {
staff.working = true;
}else{
staff.working = false;
}
break;
}
return state;
}
此代码已被罚款但我在记录器中观察到logger
,prev state
和next state
,我发现两个状态相同,但是以正确的方式,{{1} } working
中的变量应为prev state
,false
应为next state
。
现在两个处于两种状态的工作变量都是true
。
我的代码是错误的吗?
更新
组件代码如下:
true
答案 0 :(得分:1)
Reducer是一个纯函数,与action一起返回一个新版本的state或默认情况下的相同状态。
在代码中,您正在对数组中的对象进行隐式更改,从而影响它在应用程序中立即链接到的每个引用。
所以要解决它:
const staffReducer = (state = [], action) => {
switch (action.type) {
case "SET_WORKING":
return state.map((staff) => {
if (action.id === staff.id) {
return {
...staff,
working: !staff.working
}
}
return staff;
})
default:
return state;
}
}
// TO TEST the above
const initialState = [{
id: 0,
working: false
}, {
id: 1,
working: false
}, {
id: 2,
working: false
}]
console.log(initialState); // UNCHANGED
console.log(staffReducer(initialState, {
type: "SET_WORKING",
id: 2
})); // MODIFIED as expected

说明:
通过state.map
我们返回一个新的数组副本,因此数组实例的标识不同,它已经破坏了对应用程序中先前版本的引用。
但就其自身而言还不够,因为你的更改在一个更深的层次上,在一个对象的数组项级别上,所以我们还必须确保数组中对象的身份是也可以通过使用object rest spread syntax这样来破坏与旧引用的连接
return {
...staff,
working: !staff.working
};
希望它有所帮助。