Javascript 编写纯函数更新地图中的深场
我正在用react/redux构建一个树视图。折叠/展开节点时,将调度一个操作,以便将“toggled”字段设置为true/false。 下面的数组是我的redux状态的一部分Javascript 编写纯函数更新地图中的深场,javascript,reactjs,ecmascript-6,redux,Javascript,Reactjs,Ecmascript 6,Redux,我正在用react/redux构建一个树视图。折叠/展开节点时,将调度一个操作,以便将“toggled”字段设置为true/false。 下面的数组是我的redux状态的一部分 Tree:{ "id" : 1, "name": "Demo", "toggled": true, "active": false, "children": [ { "id" : 21
Tree:{
"id" : 1,
"name": "Demo",
"toggled": true,
"active": false,
"children": [
{
"id" : 21,
"name": "example",
"active": false,
"toggled": false,
children:[...]
}
}
下面的函数不好,它只返回更新了第一级节点的树,而不是嵌套的树
function createNodes(children,corporation,type){
if (!Array.isArray(children))
{
children = children ? [children] : [];
}
return children.map(node => {
createNodes(node.children,corporation,type);
if(node.id!==corporation.id){
return ({...node,active:false}: node);
}
return ({...node,toggled:corporation.toggled});
}
你知道我怎样才能有效地做到吗
干杯通常建议您尽可能保持状态平坦。我会尝试将您的状态更改为平面数组,然后更新
子属性
以包含ID列表,而不是子属性本身。大概是这样的:
状态
[
{
"id" : 1,
"name": "Demo",
"toggled": true,
"active": false,
"children": [ "21" ]
},
{
"id" : 21,
"name": "example",
"active": false,
"toggled": false,
children:[...]
}
]
然后,您的reducer将变成一个简单的列表更新:
减速器
function updateCorporation(state, newCorp) {
return state.map(function(corp) {
return corp.id === newCorp.id ? newCorp : corp
})
}
深度更新
[
{
"id" : 1,
"name": "Demo",
"toggled": true,
"active": false,
"children": [ "21" ]
},
{
"id" : 21,
"name": "example",
"active": false,
"toggled": false,
children:[...]
}
]
但是,如果您无法使用展开状态,并且需要在深层树上执行更新,则可以尝试修复原始的createNodes
函数。我认为主要的问题是,你没有使用递归来生成返回值,你只是在调用函数本身。尝试类似的方法(我已经删除了类型
,因为您没有使用它):
一般建议你尽可能保持你的状态平坦。我会尝试将您的状态更改为平面数组,然后更新
子属性
以包含ID列表,而不是子属性本身。大概是这样的:
状态
[
{
"id" : 1,
"name": "Demo",
"toggled": true,
"active": false,
"children": [ "21" ]
},
{
"id" : 21,
"name": "example",
"active": false,
"toggled": false,
children:[...]
}
]
然后,您的reducer将变成一个简单的列表更新:
减速器
function updateCorporation(state, newCorp) {
return state.map(function(corp) {
return corp.id === newCorp.id ? newCorp : corp
})
}
深度更新
[
{
"id" : 1,
"name": "Demo",
"toggled": true,
"active": false,
"children": [ "21" ]
},
{
"id" : 21,
"name": "example",
"active": false,
"toggled": false,
children:[...]
}
]
但是,如果您无法使用展开状态,并且需要在深层树上执行更新,则可以尝试修复原始的createNodes
函数。我认为主要的问题是,你没有使用递归来生成返回值,你只是在调用函数本身。尝试类似的方法(我已经删除了类型
,因为您没有使用它):
第一次调用createNodes时,我传递了一个数组,它是树而不是子树,因此我想createNodes周围应该有另一个循环,它确实有助于保持递归函数的输入一致。如果可以的话,我会尝试将整个树传入,如果没有的话,一个循环肯定会工作(您可以直接从函数中复制中间的分支,然后执行类似于
const nextChildren=children.map(…)
).快速提问:在我的初始代码中,如您所见,我添加了一段代码,用于在不是数组children=children的情况下添加方括号?[儿童]:[];正确的?我想这不好,我不应该修改州啊,我错过了。那么子元素可以是数组,也可以是单个子元素?是的,一开始就有一个一致的数据结构通常比在需要使用它时试图将其强制为单一格式要好。我已经解决了这个问题,谢谢。我想添加一个其他函数来选择树节点,当单击一个项目时,您编写的函数将允许我返回“select”字段设置为“true”的子项。但是,我还需要将旧的选定项更改为“false”,因为在树中只能选择一个。如果我按原样使用您的函数,它将显示选定的节点,但也显示上一个节点。我可以调用您的函数两次,一次用于选择,第二次用于取消选择前一个函数,但它不是很有效。我想有一种方法可以在同一个函数中实现这一点第一次调用createNodes时,我传递了一个数组,它是树而不是子树,所以我想createNodes应该有另一个循环,它确实有助于保持递归函数的输入一致。如果可以的话,我会尝试将整个树传入,如果没有的话,一个循环肯定会工作(您可以直接从函数中复制中间的分支,然后执行类似于const nextChildren=children.map(…)
).快速提问:在我的初始代码中,如您所见,我添加了一段代码,用于在不是数组children=children的情况下添加方括号?[儿童]:[];正确的?我想这不好,我不应该修改州啊,我错过了。那么子元素可以是数组,也可以是单个子元素?是的,一开始就有一个一致的数据结构通常比在需要使用它时试图将其强制为单一格式要好。我已经解决了这个问题,谢谢。我想添加一个其他函数来选择树节点,当单击一个项目时,您编写的函数将允许我返回“select”字段设置为“true”的子项。但是,我还需要将旧的选定项更改为“false”,因为在树中只能选择一个。如果我按原样使用您的函数,它将显示选定的节点,但也显示上一个节点。我可以调用您的函数两次,一次用于选择,第二次用于取消选择前一个函数,但它不是很有效。我想有一种方法可以在相同的函数中实现