首页 > 解决方案 > 如何在不变异的情况下正确更新 redux 数组中的项目?

问题描述

const state = [
    {
        list: []
    }
];

该列表是学生对象的列表,例如:

list: [
   { id: 1, name: "Mark", attendance: true },
   { id: 2, name: "John", attendance: false }
]

我有一个按钮可以触发对 API 的发布请求,以将出勤率更改为 true。发布请求返回已更改的学生对象,例如:

{ id: 2, name: "John", attendance: true }

这工作正常,如果没有错误,将调度ATTENDANCE_SUCCESS.

现在,通过这种设置:

export function students(state, action) {
    let latestState = state[state.length - 1],
        newState = Object.assign({}, latestState);
    switch (action.type) {
       case "ATTENDANCE_SUCCESS":
          if (action.res.errorCode == 0) {
             // Need to change redux state 'attendance' value to true for a student with ID returned from the POST request
          }
    }

最初,我做了:

const studentChanged = newState.list.find(function(student) {
  return (
        student.id ===
        action.res.data.id
  );
});
studentChanged.attendance = true;

但它改变了 redux 存储中的状态(尽管我不确定它是如何发生的,因为我假设 newState 已经是一个副本)。

什么是正确的方法?

标签: javascriptreactjsredux

解决方案


以下将更新数组中的单个项目。这里的关键方面是,如果id项目的 与来自操作有效负载的 不匹配id,它会返回未更改的项目,否则它会更新attendance属性。Array.prototype.map返回一个新数组,因此它是不可变的。

export function students(state, action) {
  switch (action.type) {
    case "ATTENDANCE_SUCCESS":
      if (action.res.errorCode == 0) {
        return state.map(student => {
          // we want to leave non matching items unaltered
          if (student.id !== action.res.data.id) {
            return student;
          }

          return { ...student, attendance: true };
        });
      }

      return state;          
    default:
      return state;
  }
}

这是一个StackBlitz来演示功能。

希望这会有所帮助!


推荐阅读