使用spread运算符更新非常深的对象

时间:2017-01-27 18:33:01

标签: javascript reactjs redux react-redux spread-syntax

我有一个看起来像这样的对象:

  state: {
    "1": {
      "show": false,
      "description": "one",
      "children": {
        "1": { "show": false, "description": "one" },
        "2": { "show": false, "description": "one" }
      }
    },
    "2": {
      "show": false,
      "description": "one",
      "children": {
        "1": { "show": false, "description": "one" },
        "2": { "show": false, "description": "one" }
      }
    }
  }

我有一个for循环,将子节点“show”属性更改为相反的布尔值。所以我尝试用这个更新值但是没有用。

      for (var childKey in state[appClassId].children) {
        newState = {
          ...state,
          [appClassId]: {
            children: {
              [childKey]: { ...state[appClassId].children[childKey], show: !state[appClassId].children[childKey].show}

            }
          }

“appClassId”变量是我从动作中得到的变量。

如何更新子属性中的每个键,例如state.1.children.1.show

4 个答案:

答案 0 :(得分:1)

在@markerikson作者的帮助下:

http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html

我能够更新深层次的嵌套数据:

要更新的对象是" children"下的所有对象。该对象的属性:

 state: {
    "1": {
      "show": false,
      "description": "one",
      "children": {
        "1": { "show": false, "description": "one" },
        "2": { "show": false, "description": "one" }
      }
    },
    "2": {
      "show": false,
      "description": "one",
      "children": {
        "1": { "show": false, "description": "one" },
        "2": { "show": false, "description": "one" }
      }
    }
  }

更新它的代码是:

let newState = {};
newState = { ...state, newState }

for (var childKey in newState[appClassId].children) {
  newState = {
    ...newState,
    [appClassId]: {
      ...newState[appClassId],
      children: {
        ...newState[appClassId].children,
        [childKey]: {
          ...newState[appClassId].children[childKey],
          show: !newState[appClassId].children[childKey].show
        }
      }
    }
  }
}

答案 1 :(得分:0)

如果您执行的操作比指定一两个值更复杂,我建议您继续使用a utility library like lodash.js

假设每个appClassId内的statechildrenappClass的数量完全是动态的:

import { reduce } from 'lodash'

const newState = reduce(state, (modifiedState, appClass, appClassId) => {
  const { children } = appClass
  // toggle show for each child (non-mutating)
  const toggledChildren = reduce(children, (newChildren, child, childId) => {
    return {
      ...newChildren,
      [childId]: { ...child, show: !child.show }
    }
  }, {})

  // persist modified children within the appClass
  return {
    ...modifiedState,
    [appClassId]: {
      ...appClass,
      children: toggledChildren
    }
  }
}, {})

希望这有帮助!

答案 2 :(得分:0)

试试这个:

const originalChildren = state[appClassId].children;
let updatedChildren = {};

for (var child in originalChildren) {
   if (originalChildren.hasOwnProperty(child)) {
      updatedChildren = {
        ...updatedChildren,
        [child]: { ...originalChildren[child], show: !originalChildren[child].show }
      };
   }
}

const newState = {
  ...state,
  [appClassId]: {
    ...state[appClassId],
    children: { ...originalChildren, ...updatedChildren }
  }
}

答案 3 :(得分:0)

另一个例子,

let test = [
  { id: 1, name: 'Phone',
    Devices: [
      { id: 1, name: 'BlackBerry',GroupId: 1 },
      { id: 2, name: 'Iphone', GroupId: 1 }
    ]
  }, { id: 2, name: 'Speaker',
    Devices: [
      { id: 3, name: 'Senheiser', GroupId: 2 },
      { id: 4, name: 'Simbadda', GroupId: 2 }
    ]
  }
];

const GroupId = 1;
const device = {
  id: 5,
  name: 'Android',
  GroupId: GroupId
}


let Group = [...test];

const idx = test.findIndex(payload => {
  return payload.id === GroupId
});

console.log(Group[idx].Devices = [...Group[idx].Devices, device]);

希望它会有所帮助