2016-01-15 81 views
1

我有一個深深的嵌套不可變的結構與地圖和列表。我不確定在結構中更新嵌套地圖的最佳方式(具有ID:356的節點)。Immutable.js結構(更新嵌套地圖)?

我創建了一個函數來搜索列表,我找到了目標地圖,我更新它。但結構保持完好!任何想法我做錯了什麼?

https://jsbin.com/sadoni/1/edit?js,console

var structure = Immutable.fromJS(
     { 
      someKey:{id:1}, 
      links:[ 
       {id:123, c:false, chd:[]}, 
       {id:134, c:false, chd:[ 
        {id:212, c:false, chd:[ 
         {id:245, c:false, chd:[]}, 
         {id:256, c:false, chd:[]} 
        ]}, 
        {id:145, c:false, chd:[]}, 
        {id:156, c:false, chd:[]}, 
        {id:213, c:false, chd:[ 
         {id:313, c:false, chd:[]}, 
         {id:314, c:false, chd:[ 
          {id:345, c:false, chd:[]}, 
          {id:356, c:false, chd:[]} 
         ]} 
        ]} 
       ]} 

      ] 
     } 
    ); 


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _findNode 
    function _findNode(nodes, func, cb){ 
     let found = false; 
      var findInTree = (nodes, func) => { 
       if(nodes && nodes.size > 0){ 
        nodes.forEach(node => { 
         if(found === false){ 
          if (func(node) === true) { 
           found = true; 
           cb(node, nodes); 
          } else { 
           let chd = node.get('chd'); 
           if(chd && chd.size > 0 && found === false){ 
            findInTree(chd, func); 
           } 
          } 
         } 
        }); 
       } 
      }; 
      findInTree(nodes, func, cb); 
    } 


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _filter function 
function filter(link){ return link.get('id')===356; } 

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _find the links array inside the tree 
var links = structure.get('links'); 

function changeTheNode(node, nodes){ 
    console.log(nodes.get(1).toJS()); // log nodes array before the update 
    var index = nodes.findIndex(function(n){ return n === node; }); 
    nodes = nodes.update(index, function(itm){ return itm.set('c', true); }); 
    // nodes array changed 
    console.log(nodes.get(1).toJS()); 

    // structure tree is still the same :(
    //console.log(structure.toJS()); 
} 

_findNode(links, filter, changeTheNode); 

回答

0

遞歸!

var data = Immutable.fromJS({ 
    id:134, c:false, chd:[ 
     {id:212, c:false, chd:[ 
      {id:245, c:false, chd:[]}, 
      {id:256, c:false, chd:[]} 
     ]}, 
     {id:145, c:false, chd:[]}, 
     {id:156, c:false, chd:[]}, 
     {id:213, c:false, chd:[ 
      {id:313, c:false, chd:[]}, 
      {id:314, c:false, chd:[ 
       {id:345, c:false, chd:[]}, 
       {id:356, c:false, chd:[]} 
      ]} 
     ]} 
    ] 
}); 

function search(val, target, changeTheNode) { 
    if (val.get('id') === target) { 
     return changeTheNode(val); 
    } 

    return val.set('chd', 
     val.get('chd') 
     .map((v) => search(v, target, changeTheNode)) 
    ); 
} 

var updatedData = search(data, 356, (node) => node.set('c', true)) 

結果是

{ 
    "id": 134, 
    "c": false, 
    "chd": [ 
    { 
     "id": 212, 
     "c": false, 
     "chd": [ 
     { 
      "id": 245, 
      "c": false, 
      "chd": [] 
     }, 
     { 
      "id": 256, 
      "c": false, 
      "chd": [] 
     } 
     ] 
    }, 
    { 
     "id": 145, 
     "c": false, 
     "chd": [] 
    }, 
    { 
     "id": 156, 
     "c": false, 
     "chd": [] 
    }, 
    { 
     "id": 213, 
     "c": false, 
     "chd": [ 
     { 
      "id": 313, 
      "c": false, 
      "chd": [] 
     }, 
     { 
      "id": 314, 
      "c": false, 
      "chd": [ 
      { 
       "id": 345, 
       "c": false, 
       "chd": [] 
      }, 
      { 
       "id": 356, 
       "c": true, 
       "chd": [] 
      } 
      ] 
     } 
     ] 
    } 
    ] 
} 
+1

注意,這和原來的不同之處在於改變的值被傳遞迴堆棧。如果你使用不可變的結構,你不能改變它。如果您需要進行更改,您必須創建一個新的並傳遞給您。原件通過調用'set'來創建新對象,但是然後將其放在地板上。 –

+0

謝謝。但是這個解決方案總是返回一個新的不可變結構,即使沒有值被改變。 var updatedData = search(data,356,(node)=> node.set('c',false)); console.log(updatedData === data); //即使沒有改變,也總是爲假 –

+1

@AshrafFayad當然是。這是不可改變的結構。他們不會變異。如果你想要可變結構不使用ImmutableJS。 –