【问题标题】:How to update deeply, recursively nested array of objects in react如何在反应中深度更新递归嵌套的对象数组
【发布时间】:2021-05-16 18:08:11
【问题描述】:
[
   {
       "id": 339,
       "children": [
           {
               "id": 381,
               "children": [
                   {
                       "id": 383,
                       "children": [],
                       "name": "Capability_C",
                       "level": 3,
                   }
               ],
               "name": "Capability_B",
               "level": 2,
           }
       ],
       "name": "Capability_A",
       "level": 1,
   }

] 

如何在我的 reducer 中正确更新这个嵌套对象(状态有这些对象的列表,而有效负载有一个可以是嵌套对象的特定对象

        return [...state, payload];

【问题讨论】:

  • case CREATE_CAPABILITY: return [...state, payload];

标签: reactjs react-redux


【解决方案1】:

您的数据结构的递归性使得这是一项不平凡的任务。您需要一种方法来进入它,处理错误的路径,并为您更新的任意深度动态克隆您的状态。

您需要一个看起来像这样的操作,其中路径数组是一个 ID 编号列表,可让您进入数据:

{
  type: "CREATE_CAPABILITY";
  payload: {
    path: Array<number>;
    capability: CapabilityObject;
  }
}

然后在您的 reducer 中,将此操作与当前 reducer 状态一起传递给递归函数:

// function

const insertCapability = (state, action) => {
  const { path, capability } = action.payload;

  if (path.length === 0) return [...state, capability];

  const nextId = path.shift();
  const childIdx = state.findIndex(cap => cap.id === nextId);

  if (childIdx < 0) return state;

  const nextChild = {
    ...state[childIdx],
    children: insertCapability(state[childIdx].children, action)
  }
  
  return (s => {s[childIdx] = nextChild; return s;})([...state]);
};

// test case

const state = [
   {
       "id": 339,
       "children": [
           {
               "id": 381,
               "children": [
                   {
                       "id": 383,
                       "children": [],
                       "name": "Capability_C",
                       "level": 3,
                   }
               ],
               "name": "Capability_B",
               "level": 2,
           }
       ],
       "name": "Capability_A",
       "level": 1,
   }
];

const action = {
  type: "CREATE_CAPABILITY",
  payload: {
    path: [339, 381, 383],
    capability: {
      id: 400,
      children: [],
      name: "New Capability",
      level: 4, 
    }
  }
}

console.log(insertCapability(state, action));

注意每次状态返回新数据时,它是在一个新数组中完成的 - [...state] - 并且每个路径进入的新子节点也被克隆 - ...state[childIdx]。这样做很重要,这样您的状态结构才能保持不变。未能正确克隆状态并意外改变状态可能会导致以后出现一些丑陋的错误。

【讨论】:

  • 你是个天才
  • 如果你觉得有用,记得点赞或标记接受。如果您想对所使用的过程进行任何解释,请询问。
猜你喜欢
  • 2018-02-14
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 2021-08-10
  • 1970-01-01
  • 2022-06-16
  • 2021-06-25
  • 1970-01-01
相关资源
最近更新 更多