在以下代码片段中,我有一个工作正常的reducer,我认为这是不正确的,因为它正在重用现有状态而不是替换它。它确实可以正常工作,但没有出现与我有关的错误。
进入这个化简器的状态只是一个只有第一级对象的简单数组。也就是说,像这样:
const stateIn = [{id: 101,favorite: 0},{id: 102,favorite: 1},...]
我怀疑的减速器如下:
const speakersReducer = (state, action) => {
switch (action.type) {
case "loadspeakers": {
return action.data;
}
case "favorite": {
return state.map((item, index) => {
if (item.id === action.sessionId) {
// let speakerToUpdate = Object.assign(item);
// speakerToUpdate.favorite = 1;
item.favorite = 1;
return item;
// return speakerToUpdate;
}
return item;
});
}
...
default:
return state;
}
};
export default speakersReducer;
答案 0 :(得分:0)
这正确吗?
正如@Tholle所指出的,item
中的"favorite"
突变确实是可疑的。减速器中的突变通常被认为是一种反模式,并且经常会导致错误。我绝对建议将其更改为不可变模式。
但是然后...
假设不正确,为什么这不会导致错误?
Reducer中的可变性是常见的错误来源,但是特定的突变位是否会引起错误,取决于其突变方式以及Reducer的使用方式。
尽管收藏夹情况可能会错误地将item
对象从状态的一个版本重用到另一状态,但由于Array.prototype.map
总是返回一个新的数组,因此它总是产生一个新的状态数组。因此,例如,useReducer
仅关心外部状态对象的身份,尽管发生了突变,它仍将正确触发重新渲染。
另一方面,记忆在数组中特定项目上的redux选择器会错误地返回旧值。而且,如果将旧的items
缓存并重新使用,则该突变也可能在此引起意外错误。但是这些是相当具体的情况,因此在大多数情况下,我怀疑这是可行的。 (不过,我仍然会将其更改为不变异)
有什么工具可以帮助我验证状态更新的正确性吗?
您想要的是某种形式的不变性:JS中有许多用于不变性的库。
还可以单独使用Typescript,也可以将它们与这些库结合使用:允许将对象和数组声明为只读,并且如果对它们进行更改会引起编译器错误。
linter规则也可能会有所帮助,但除非您可以禁止整个代码库中的所有变异,否则手动操作精简器中的规则,否则将非常棘手。