如何在react中更新深度、递归嵌套的对象数组


[
{
"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];

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

你需要一个类似这样的操作,其中路径数组是一个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]中。重要的是要做到这一点,以便您的状态结构保持不变。如果不能正确地克隆状态,并意外地对其进行突变,可能会导致以后出现一些丑陋的错误。

最新更新