在尝试用测试覆盖我的 React/Redux 应用程序时,我遇到了以下问题:我的 reducer 更改了初始状态对象,尽管我在 reducer 内复制了该对象。
这是 reducer 代码:
[actionTypes.POINT_REMOVE]: (state, action) => {
const newState = { ...state }
const { byId, ids } = newState;
const { id } = action;
ids.splice(ids.indexOf(id), 1);
delete byId[id];
return {
...newState,
byId: {
...byId
},
ids: [...ids],
};
},
这是测试代码:
describe('with non-empty state', () => {
const firstId = 123;
const secondId = 456;
const thirdId = 789;
const initialState = {
byId: {
[firstId]: {
id: firstId,
},
[secondId]: {
id: secondId,
},
[thirdId]: {
id: thirdId,
},
},
ids: [firstId, secondId, thirdId],
};
describe('on POINT_REMOVE action', () => {
it('should remove point', () => {
const expectedState = {
byId: {
[secondId]: {
id: secondId,
},
[thirdId]: {
id: thirdId,
},
},
ids: [secondId, thirdId],
};
const action = actionCreators.removePoint(firstId);
const actualState = pointsReducer(initialState, action);
expect(actualState).toEqual(expectedState);
});
});
describe('on POINT_OREDER_CHANGE action', () => {
it('should change order of elements in ids array', () => {
const oldIndex = 1;
const newIndex = 2;
console.log(initialState);
const expectedState = {
byId: {
[firstId]: {
id: firstId,
},
[secondId]: {
id: secondId,
},
[thirdId]: {
id: thirdId,
}
},
ids: [firstId, thirdId, secondId],
};
const action = actionCreators.changePointOrder({ oldIndex, newIndex });
const actualState = pointsReducer(initialState, action);
expect(actualState).toEqual(expectedState);
});
});
当我在on POINT_ORDER_CHANGE action
block 中将initialState
值记录到控制台时,它给了我没有第一个元素的initialState
值,就好像它一样在 POINT_REMOVE
reducer 内部进行了修改。
我做错了什么? 谢谢!
最佳答案
我相信您的问题可能与此行有关:
const newState = { ...state }
newState 确实是 state
的副本,但它不会是深拷贝。这意味着嵌套在 state
对象中的对象将通过引用复制,而不是将值重新创建为新对象。也就是说,您正在修改原始的 byId
和 id
对象。这样,原来的对象就会被更新。如果您不希望发生这种情况,则需要深度克隆状态对象,或者复制 byId
和 id
并将突变应用于这些对象,而不是复制它们原始对象。
byId
和 id
(个人首选方法)
const newState = { ...state }
const { byId, ids } = newState;
const { id } = action;
const copyById = { ...byId };
const copyIds = [...ids];
或状态的深度克隆
:
const newState = JSON.parse(JSON.stringify(state));
关于javascript - 对象无法正确复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57972223/