使用 immutable.js 更新 React/Redux 中深层对象值的状态

Updating state of deep object value in React/Redux using immutable.js

我有这个嵌套很深的状态数组,需要按员工、任务和周更新小时字段。我已经尝试了多种方法来使用 Immutable 来做到这一点,但没有成功,有什么帮助吗?

这是我的数据示例:

[{
  "Employee": "John Doe",
  "Other Data": "test",
  "Tasks": [{
    "AccessType": "Confidential",
    "DueDate": "2016-02-26 23:59:59",
    "taskId": "3",
    "TaskTitle": "testTitle",
    "Weeks": {
      "2016-10-10": {
        "Hours": "3"
      }
    }
  }]
}, {
  "Employee": "Bill Der",
  "Other Data": "test",
  "Tasks": [{
    "AccessType": "Confidential",
    "DueDate": "2016-02-26 23:59:59",
    "taskId": "3",
    "TaskTitle": "testTitle",
    "Weeks": {
      "2016-10-10": {
        "Hours": "3"
      }
    }
  }]
}]

你错过了很多信息让我为你完整地回答这个问题,但我可以告诉你我会如何做这样的事情。

您可以利用immutable js 为您提供的所有功能。因此,假设您有一个对象,其中包含改变不可变对象所需的信息,如下所示:

var changeHours = {
  "Employee": "John Doe",
  "TaskTitle": "testTitle",
  "Week": '2016-10-10',
  "Hours": "5"
}

我们有一个基本状态,就像您在那里设置的那样:

 var myState = Immutable.fromJS([{
  "Employee": "John Doe",
  "Tasks": [{
    "AccessType": "Confidential",
    "DueDate": "2016-02-26 23:59:59",
    "taskId": "3",
    "TaskTitle": "testTitle",
    "Weeks": {
      "2016-10-10": {
        "Hours": "3"
      }
    }
  }]
}]);

注意:我没有添加更多的数组,但我们将对它们进行映射,以便将它们考虑在内。

您可以使用不可变映射来遍历并找到您要查找的项目,如下所示:

  var newstate = myState.map((k, v) => {
  if (k.get('Employee') === changeHours.Employee) {
    return k.get('Tasks').map((k, v) => {
      if (k.get('TaskTitle') === changeHours.TaskTitle) {
                return k.setIn(['Weeks', changeHours.Week, 'Hours'], changeHours.Hours);
      }
      return k;
    })
    return k;
  }
 return k;
});

查看实际效果 - http://fiddle.jshell.net/djj6u8xL/63/。我使用 map 遍历每个数组级别,并通过基于我们的 changeHours 对象和不可变对象进行检查来找到正确的节点,然后一旦我处于正确的级别,我就使用 setIn。你也可以使用updateIn,这取决于你的场景。

以后请提供你问题的所有信息,而不仅仅是数据图片,这样会更容易帮助你:)(而且不必手动输入数据结构)。

编辑:根据评论更新 - http://fiddle.jshell.net/qxbq1nq3/9/

代码:

  function newTasks(k) {
  return k.get('Tasks').map((k, v) => {
    if (k.get('TaskTitle') === changeHours.TaskTitle) {
      return k.setIn(['Weeks', changeHours.Week, 'Hours'], changeHours.Hours);
    }
    return k;
  });
}

var newstate = myState.map((k, v) => {
  if (k.get('Employee') === changeHours.Employee) {
    return k.set('Tasks', newTasks(k));
  }
  return k;
});