在尝试用测试覆盖我的React / Redux应用程序时,我发出了以下问题:尽管我在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);
});
});
虽然我在initialState
块中将on POINT_ORDER_CHANGE action
值登录到控制台,但它却给了我initialState
值而没有第一个元素,就好像它是在POINT_REMOVE
reducer中修改的一样。 / p>
我做错了什么? 谢谢!
答案 0 :(得分:1)
我相信您的问题很可能与以下内容有关:
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];
或state
的深克隆版本:
const newState = JSON.parse(JSON.stringify(state));