如果我已经完全替换了状态的一部分,我是否仍然需要使用 Object.assign 或扩展运算符来复制原始状态并将其替换为新状态,或者我可以直接返回我的 reducer 中的新状态?
const fetching = (state = { isFetching: false }, action) => {
switch (action.type) {
case 'REQUESTING':
return Object.assign({}, state, { isFetching: true } )
case 'RECEIVE_POKEMON_TYPE_INFO':
return Object.assign({}, state, { isFetching: false } )
default:
return state
}
}
对比
const fetching = (state = { isFetching: false }, action) => {
switch (action.type) {
case 'REQUESTING':
return { isFetching: true }
case 'RECEIVE_POKEMON_TYPE_INFO':
return { isFetching: false }
default:
return state
}
}
最佳答案
这里发生了几件事。基本上,如果您的状态 仅 由一个 bool 变量组成,那么通过枚举创建一个新对象就可以了。但是,如果您的状态包含其他内容,那么执行 object.assign 应该可行。
但是(并不总是有“但是”),如果您的状态很复杂——即它由其他对象组成,那么执行 object.assign 将无法正确复制字段——它复制的是引用而不是值。例如,如果您的状态包含一个“currentlySelectedPokemon”字段,该字段的值是一个 Pokemon 对象,那么 Object.assign 将复制对 pokemon 对象的引用。它不会复制对象本身。为了更容易地展示这一点,请看下面的代码 - 它为 obj2 打印“value2”。
var obj1 = {
field: {
subfield: "value"
}
};
var obj2 = Object.assign({}, obj1);
obj1.field.subfield = "value2";
console.log(JSON.stringify(obj2, null, 2));
有两种方法可以解决这个问题。第一种是对所有状态使用 Immutable 库。但是,我发现将复杂对象转换为 Immutable 并返回的开销提供了足够的复杂性,从而引入了不必要的错误。所以现在我这样做:
const fetching = (state = { isFetching: false }, action) => {
switch (action.type) {
case 'REQUESTING':
const newState = JSON.parse(JSON.stringify(state));
newState.isFetching = true;
return newState;
case 'RECEIVE_POKEMON_TYPE_INFO':
const newState = JSON.parse(JSON.stringify(state));
newState.isFetching = false;
return newState;
default:
return state
}
}
事实证明,JSON.parse(JSON.stringify(object)) 是制作普通 java 对象副本的快速可靠方法。它剥离了所有功能(这是我通常想要的)。而且速度很快,因为浏览器通常以 native 代码实现这些功能。
关于javascript - 在不制作副本的情况下替换 react redux reducer 中的新状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39200206/