如果我已经完全替换了整个状态片段,我是否还必须使用Object.assign或spread运算符来复制原始状态并将其替换为新状态,或者我可以返回我的减速机中的新状态?
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
}
}
VS
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
}
}
答案 0 :(得分:4)
这里有几件事情要发生。基本上,如果您的状态仅包含布尔变量,那么通过枚举创建新对象就可以了。但是,如果您的状态包含其他内容,则执行object.assign应该可以正常工作。
然而(并且并不总是'然而'),如果你的状态很复杂 - 那就是它由其他对象组成然后做object.assign将无法正确复制字段 - 它复制了引用而不是值。例如,如果您的状态由“currentSelectedPokemon”字段组成,那么值是一个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和back的开销提供了足够的复杂性,从而引入了不必要的错误。所以现在我这样做:
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))是一种快速可靠的方法来制作一个vanilla java对象的副本。它剥离了所有功能(这是我通常想要的)。它很快,因为浏览器通常在本机代码中实现这些功能。
答案 1 :(得分:0)
您可以使用Object.assign
或spread operator
,如下所示
使用Object.assign
:
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 { ...state, isFetching: true }
case 'RECEIVE_POKEMON_TYPE_INFO':
return { ...state, isFetching: false }
default:
return state
}
}
使用Object.assign()
可以快速地使简单的reducer难以阅读,因为它相当verbose syntax
。spread (...)
运算符以更简洁的方式将可枚举属性从一个对象复制到另一个对象。