在 Reducer 中更新对象 属性 而不改变

Updating Object Property in Reducer without Mutation

我觉得我的 reducer 应该可以工作,但它一直坚持我正在改变状态。

Uncaught Error: A state mutation was detected inside a dispatch, in the path: output.outputList.0.composition. Take a look at the reducer(s) handling the action {"type":"SET_OUTPUT_COMPOSITION",

几个小时前我发布了类似的东西但没有答案,但我认为我的 redux 状态太复杂了。这是我的简化版本,我仍然遇到变异错误..我做错了什么?我不应该在我的 redux 状态下使用 class 吗?我应该使用某种不可变的库吗?请帮助我。

我的初始 Redux 状态

output: {
    outputList: [], //composed of Output class objects
    position: 0
  }

输出Class

class Output {

  constructor(output) {
      this.id = output.id;
      this.composition = output.getComposition();
      this.outputObj = output;
      this.name = output.name;
      this.url = output.getUrl();    
  }
}

export default Output;

用于更新的减速器属性

case types.SET_OUTPUT_COMPOSITION: {
      let outputListCopy = Object.assign([], [...state.outputList]);
      outputListCopy[state.position].composition = action.composition;
      return Object.assign({}, state, {outputList: outputListCopy});

动作

export function setOutputComposition(comp) {
 return { type: types.SET_OUTPUT_COMPOSITION, composition: comp}
}

错误来自 dispatch。所以它甚至没有达到 reducer。我希望它不喜欢你使用 class 来定义 output。而只是做 const output ={ ... }

spread operator 没有深度复制原始列表中的对象:

let outputListCopy = Object.assign([], [...state.outputList]);

是浅拷贝,因此

outputListCopy[state.position].composition = action.composition;

你实际上是在改变以前的状态对象,正如你在评论中所说,有几种方法可以解决这个问题,使用 slice/splice 创建数组的新实例等。

你也可以看看使用 ImmutableJS,一般来说,我会说在 redux store 中存储 类 会使事情有点难以理解,我倾向于支持简单的结构可以使用 redux-tools 轻松检查。