Redux Reducer如何更新规范化状态的子节点

时间:2017-04-25 15:04:22

标签: javascript reactjs redux normalizr

我有一个有效负载A代表一个n深的嵌套树,看起来像..(你可以把section数组想象成树上的子节点)

const data = {
  id: 123,
  sections: [{
    id: 1,
    sections:[{ id: 4, sections: [ { id: 5, sections: [] } ] }]
  }, {
    id: 2,
    sections:[]
  }, {
    id: 3,
    sections:[]
  }]
};

有效负载A的规范化状态如下所示

    {
  "entities": {
    "sections": {
      "1": { "id": 1, "sections": [ 4 ] },
      "2": { "id": 2, "sections": [] }, 
      "3": { "id": 3, "sections": [] },
      "4": { "id": 4, "sections": [ 5 ] },
      "5": { "id": 5, "sections": [] }
    },
    "menu": {
      "123": { "id": 123, "sections": [ 1, 2, 3 ] }
    }
  },
  "result": 123
}

如果用户要扩展第5节,我会离开并从服务器加载更多子节点。标准化后从服务器返回的有效负载B看起来像

{
  "entities": {
    "sections": {
      “6”: { "id": 6, "sections": [] }, 
    },
    "menu": {
      "1234”: { "id": 1234, "sections": [ 6 ] }
    }
  },
  "result": 1234
}

如何编写一个reducer来组合(合并/映射等)规范化的有效负载A和规范化的有效负载B,以便新的Redux存储状态如下所示......

    {
  "entities": {
    "sections": {
      "1": { "id": 1, "sections": [ 4 ] },
      "2": { "id": 2, "sections": [] }, 
      "3": { "id": 3, "sections": [] },
      "4": { "id": 4, "sections": [ 5 ] },
      "5": { "id": 5, "sections": [6] },
    “6”: { "id": 6, "sections": [] }
    },
    "menu": {
      "123": { "id": 123, "sections": [ 1, 2, 3 ] }
    }
  },
  "result": 123
}

2 个答案:

答案 0 :(得分:0)

它应该不难实现,在你的reducer中我确定你保持以前的状态,以下列方式从以前的状态entities.sections中取出值

var newData = {...state.entities.sections,newSectionPayload}

newSectionPayload应包含新扩展部分的数据。

我没有尝试过,但我很确定它应该可行。

答案 1 :(得分:-1)

这是我的减速器,以解决上述问题,似乎可以解决这个问题

<p>@ViewBag.Property1</p>
<p>@ViewBag.Property2</p>

TreeNodesSchema也看起来如下。

export const productHierarchyReducer: ActionReducer<ProductHierarchyState> = (state:any={}, action: Action) => {
   switch (action.type) {
        case ADD_PRODUCTHIERARCHY:
             const normalizedTreeNodes = normalize(action.payload, TreeNodesSchema);          
             return normalizedTreeNodes; 
         case ADD_PRODUCTHIERARCHY_CHILDREN:

                   const {targetNodeId, payload} = action.payload;
                   const normalizedChildNodes = normalize(payload, TreeNodesSchema);   

                   const expandTargetNode=dotProp.set(
                        state, 
                         `entities.children.${targetNodeId}.expanded`, 
                            expanded => true
                        );

                     const updatedWithNewChildren = dotProp.set(
                        expandTargetNode, 
                         `entities.children.${targetNodeId}.children`, 
                            children => 
                            children.concat(normalizedChildNodes.entities.nodes[normalizedChildNodes.result].children)
                        );

                     const newState=dotProp.set(updatedWithNewChildren, 
                         `entities.children`,
                           children =>  Object.assign({}, children, normalizedChildNodes.entities.children) 
                         )   

                   return newState;

        default:
            return state;
    }    
};
export const ProductHierarchyReducer = {
    productHierarchy: productHierarchyReducer
}

dotProp.set()语法属于dot-prop-immutable https://github.com/debitoor/dot-prop-immutable

有关更新规范化状态的资源非常有用 http://redux.js.org/docs/recipes/reducers/UpdatingNormalizedData.html