编写一个纯函数来更新地图中的深度字段

时间:2017-01-05 13:27:43

标签: javascript reactjs ecmascript-6 redux

我用react / redux建立一个树视图。折叠/展开节点时,会调度一个操作,以便切换"切换" field设置为true / false。 下面的数组是我的redux状态的一部分。

 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});

}

知道如何才能有效地做到这一点吗?

欢呼声

1 个答案:

答案 0 :(得分:4)

通常建议您尽可能保持您的州一样平坦。我会尝试将您的状态更改为平面数组,然后更新children属性以包含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
    })
}

深度更新

但是,如果您无法使用平面状态并需要在深树上进行更新,则尝试修复原始createNodes功能。我认为主要问题是你没有使用递归来生成返回值,你只是在其自身内部调用函数。尝试这样的事情(我已经放弃了type,因为你没有使用它):

function createNodes(state, corporation) {
    if (state.id === corporation.id) {
        return { ...state, toggled: corporation.toggled }
    } else if (Array.isArray(state.children)) {
        const children = state.children.map(function(child){
            return createNodes(child, corporation)
        })
        return { ...state, children }
    } else {
        return state
    }
}