尽管 Object.assign 和 Spread 语法,对象在 Redux 中发生变异

Object mutates in Redux despite Object.assign and Spread syntax

我在 Redux Saga 中有一个生成器函数,它获取一个 ID,获取状态并分派一个带有状态的动作,其中没有带有匹配 ID 的对象键。 reducer 中的对象它应该被替换而不是变异看起来像这样:

{
    [CURRENT YEAR]: {
      [DAY OF YEAR]: {
        [ID THAT SHOULD BE DELETED]: {}
      },
    },
};

当此函数 运行 使用注释掉的删除运算符时,它将改变 redux 和所有 Redux 记录器(更改前和更改后)中的整个状态,而我的选择器将 return 之前的记忆版本,因为未检测到任何更改。我通过使用 lodash Omit 创建一个新对象解决了这个问题,但是有没有更快或小于 21kb 的解决方案?

function* removeExerciseAsync(action: any) {
  const { currentDate, currentYear }: DateState = yield select((state: AppState) => state.date);
  const years = yield select(selectYears);

  const dayOfYear = currentDate.dayOfYear();


  const newYearState: DaySummaryTypes = Object.assign({}, years[currentYear]);

  const exerciseId = action.payload;

  if (!newYearState[dayOfYear][exerciseId]) return;

  // delete newYearState[dayOfYear][exerciseId];

  const newState = omit(newYearState, `${dayOfYear}.${exerciseId}`);

  yield put(updateYearExercises({ [currentYear]: newState }));
}

Object.assign 对对象进行浅拷贝,意味着顶层的对象不同但嵌套对象仍然引用以前的对象。在这里,您正在更改与 redux 存储中的对象具有相同引用的嵌套对象,因此改变了 redux 状态。您也可以尝试像这样复制嵌套对象:

function* removeExerciseAsync(action: any) {
  const { currentDate, currentYear }: DateState = yield select((state: AppState) => state.date);
  const years = yield select(selectYears);

  const dayOfYear = currentDate.dayOfYear();


  const newYearState: DaySummaryTypes = {
    ...years[currentYear],
    [dayOfYear]: {
      ...years[currentYear][dayOfYear]
    }
  };

  const exerciseId = action.payload;

  if (!newYearState[dayOfYear][exerciseId]) return;

  delete newYearState[dayOfYear][exerciseId];

  // const newState = omit(newYearState, `${dayOfYear}.${exerciseId}`);

  yield put(updateYearExercises({ [currentYear]: newState }));
}