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

Posted

技术标签:

【中文标题】使用扩展运算符更新非常深的对象【英文标题】:Update very deep object with spread operator 【发布时间】:2017-06-13 12:48:46 【问题描述】:

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

  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 循环将子“显示”属性更改为相反的布尔值。所以我尝试用这个来更新值,但是没有用。

      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

【问题讨论】:

你能看看 redux 文档中的Normalizing State Shape 吗?我认为它会帮助你正常化你的状态并能够轻松地更新它! 它是标准化的,看看它在你的链接中给出的例子。 实际上,作为“结构化减速器”部分的作者,我认为“不可变更新模式”部分更相关:redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html 【参考方案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
        
      
    
  

【讨论】:

【参考方案2】:

如果您做的事情比分配一个或两个值更复杂,我建议您使用 a utility library like lodash.js 和扩展运算符。

假设statechildren 中的appClassIds 的数量在每个appClass 中是完全动态的:

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
    
  
, )

希望这会有所帮助!

【讨论】:

【参考方案3】:

试试这个:

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 
  

【讨论】:

【参考方案4】:

另一个例子,

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

希望对你有帮助

【讨论】:

以上是关于使用扩展运算符更新非常深的对象的主要内容,如果未能解决你的问题,请参考以下文章

扩展运算符在对象的数组内分配数据

JavaScript |扩展运算符更新嵌套值

使用扩展运算符替换集合的对象

ES6扩展运算符的用途

无法在 React 中使用扩展运算符更新状态

ES6对象扩展——扩展运算符