reactjs - 如何在反应中深度更新递归嵌套的对象数组
问题描述
[
{
"id": 339,
"children": [
{
"id": 381,
"children": [
{
"id": 383,
"children": [],
"name": "Capability_C",
"level": 3,
}
],
"name": "Capability_B",
"level": 2,
}
],
"name": "Capability_A",
"level": 1,
}
]
我如何在我的减速器中正确更新这个嵌套对象(状态有这些对象的列表,而有效负载有一个可以是嵌套对象的特定对象
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]
。这样做很重要,这样您的状态结构才能保持不变。未能正确克隆状态并意外地对其进行变异可能会在以后导致一些丑陋的错误。
推荐阅读
- javascript - 在哪里存储 Node 应用程序的 Firebase 私钥
- python - 当订阅者断开连接时,如何从发布者恢复丢弃的消息?
- ipython - 安装新包后重新启动 IPython 内核 - Hydrogen vs Jupyter
- xaml - MSBuild:UpdateDesignTimeXaml 有什么作用?
- c# - 缓存设备上下文
- angular - 将前端从 web 动态加载到 Angular:可能吗?
- python - 使用python进行多线程加密的问题
- r - 在R中的变量上选择具有特定值的每组的最后两行
- xslt - 问题:SVG
- angular - 当我使用方法填充行时,ag-grid Cell Renderer 停止工作