对象无法正确复制

时间:2019-09-17 10:22:39

标签: javascript redux

在尝试用测试覆盖我的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>

我做错了什么? 谢谢!

1 个答案:

答案 0 :(得分:1)

我相信您的问题很可能与以下内容有关:

    const newState = { ...state }

newState实际上将是state的副本,但是不会是深层副本。这意味着嵌套在state对象中的对象将通过引用复制,而不是将值重新创建为新对象。也就是说,您正在修改原始的byIdid对象。按照这里的方式,原始对象将被更新。如果您不希望这种情况发生,则需要深度克隆状态对象,或者制作byIdid的副本,然后将突变应用于原始对象而不是原始对象。

例如: 制作byIdid(个人偏爱的方法)的副本

  const newState = { ...state }
    const { byId, ids } = newState;
    const { id } = action;
    const copyById = { ...byId };
    const copyIds = [...ids];

state的深克隆版本:

const newState = JSON.parse(JSON.stringify(state));