不可移动地移除对象中的属性

不可移动地移除对象中的属性

问题描述:

我正在使用Redux。在我的减速器我想从这样一个对象中删除一个属性:不可移动地移除对象中的属性

const state = { 
    a: '1', 
    b: '2', 
    c: { 
     x: '42', 
     y: '43' 
    }, 
} 

而且我希望有这样的事情,而不必变异原始状态:

const newState = { 
    a: '1', 
    b: '2', 
    c: { 
     x: '42', 
    }, 
} 

我尝试:

let newState = Object.assign({}, state); 
delete newState.c.y 

但由于某些原因,它从两种状态中删除属性。

能帮我做到吗?

只需使用ES6对象解构功能

const state = { 
 
    c: { 
 
     x: '42', 
 
     y: '43' 
 
    }, 
 
} 
 

 
const { c: { y, ...c } } = state // generates a new 'c' without 'y' 
 

 
console.log({...state, c }) // put the new c on a new state

这是因为您正在将state.c的值复制到另一个对象。该值是一个指向另一个JavaScript对象的指针。所以,这两个指针都指向同一个对象。

试试这个:

let newState = Object.assign({}, state); 
console.log(newState == state); // false 
console.log(newState.c == state.c); // true 
newState.c = Object.assign({}, state.c); 
console.log(newState.c == state.c); // now it is false 
delete newState.c.y; 

你也可以做对象的深副本。见this question,你会发现什么是最适合你的。

+2

这是一个很好的答案! 'state.c'是一个引用,并且引用被复制得很好。 Redux想要一个规范化的状态形状,这意味着在嵌套状态时使用id而不是引用。看看REDX文档:http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html – Ziggy

我发现ES5阵列方法,如filter,mapreduce有用,因为它们总是返回新的数组或对象。在这种情况下,我会使用Object.keys遍历该对象,然后使用Array#reduce将其重新转换为对象。

return Object.assign({}, state, { 
    c: Object.keys(state.c).reduce((result, key) => { 
     if (key !== 'y') { 
      result[key] = state.c[key]; 
     } 
     return result; 
    }, {}) 
}); 
+0

以我的微小变化为目标,使它更清晰IMO ...也让你省略多个属性。 const omit = ['prop1','prop2'] ... if(omit.indexOf(key)=== -1)result [key] = state.c [key] return result; ... –

+0

ES6相当于使用键“myKey”获得'myObject'副本:'Object.keys(myObject).reduce((acc,cur)=> cur === myKey?acc:{... acc,[ cur]:myObject [cur]},{})' – transang

您可以使用_.omit(object, [paths])lodash

路径可以被嵌套,例如:_.omit(object, ['key1.key2.key3'])

+3

不幸的是,'_.omit'不能删除深层属性(OP所要求的)。为此,有['omit-deep-lodash'](https://www.npmjs.com/package/omit-deep-lodash)模块。 – AlexM

如何:

function removeByKey (myObj, deleteKey) { 
    return Object.keys(myObj) 
    .filter(key => key !== deleteKey) 
    .reduce((result, current) => { 
     result[current] = myObj[current]; 
     return result; 
    }, {}); 
} 

它过滤应然后删除密钥从剩余的键和初始对象中构建一个新对象。这个想法从Tyler McGinnes真棒reactjs程序中被盗。

JSBin

这很容易与Immutable.js

const newState = state.deleteIn(['c', 'y']); 

description of deleteIn()

function dissoc(key, obj) { 
    let copy = Object.assign({}, obj) 
    delete copy[key] 
    return copy 
} 

而且,如果寻找一个函数式编程工具包,看看Ramda

您可以使用Immutability helper以取消设置的属性,你的情况:

import update from 'immutability-helper'; 

const updatedState = update(state, { 
    c: { 
    $unset: ['y'] 
    } 
});  

如何使用destructuring assignment语法?

const original = { 
 
    foo: 'bar', 
 
    stack: 'overflow', 
 
}; 
 

 
// If the name of the property to remove is constant 
 
const { stack, ...withoutFirst } = original; 
 
console.log(withoutFirst); // Will be { "foo": "bar" } 
 

 
// If the name of the property to remove is from a variable 
 
const key = 'stack' 
 
const { [key]: value, ...withoutSecond } = original; 
 
console.log(withoutSecond); // Will be { "foo": "bar" } 
 

 
// To do a deep removal with property names from variables 
 
const deep = { 
 
    foo: 'bar', 
 
    c: { 
 
    x: 1, 
 
    y: 2 
 
    } 
 
}; 
 

 
const parentKey = 'c'; 
 
const childKey = 'y'; 
 
// Remove the 'c' element from original 
 
const { [parentKey]: parentValue, ...noChild } = deep; 
 
// Remove the 'y' from the 'c' element 
 
const { [childKey]: removedValue, ...childWithout } = parentValue; 
 
// Merge back together 
 
const withoutThird = { ...noChild, [parentKey]: childWithout }; 
 
console.log(withoutThird); // Will be { "foo": "bar", "c": { "x": 1 } }

+0

美妙,没有额外的库,使用es6和足够简单。 – sbk201

+0

最优雅的解决方案 –

+1

不错!这里有一个es6帮助函数,它和它一起'const deleteProperty =({[key]:_,... newObj},key)=> newObj;'。用法:'deleteProperty({a:1,b:2},“a”);'给出'{b:2}' – mikebridge

我通常使用

Object.assign({}, existingState, {propToRemove: undefined}) 

我知道这是不是真正删除的财产,但几乎所有的目的其功能上等同。这个语法比我认为是一个很好的折衷方案更简单。

如果您使用的是hasOwnProperty(),则需要使用更复杂的解决方案。

正如已经暗示的一些答案,这是因为你试图修改一个嵌套的状态,即。更深一层。一个典型的解决方案将是在x*加减速:

const state = { 
    a: '1', 
    b: '2', 
    c: { 
     x: '42', 
     y: '43' 
    }, 
} 

更深层次的减速

let newDeepState = Object.assign({}, state.c); 
delete newDeepState.y; 

原有水平减速

let newState = Object.assign({}, state, {c: newDeepState}); 

我使用这个模式

const newState = Object.assign({}, state); 
     delete newState.show; 
     return newState; 

但是在本书中,我看到了另一种模式

return Object.assign({}, state, { name: undefined }) 

效用;))

const removeObjectField = (obj, field) => { 

    // delete filter[selectName]; -> this mutates. 
    const { [field]: remove, ...rest } = obj; 

    return rest; 
} 

动作类型

const MY_Y_REMOVE = 'MY_Y_REMOVE'; 

行动的创建者

const myYRemoveAction = (c, y) => { 

    const result = removeObjectField(c, y); 

     return dispatch => 
      dispatch({ 
       type: MY_Y_REMOVE, 
       payload: result 
      }) 
    } 

减速

export default (state ={}, action) => { 
    switch (action.type) { 
    case myActions.MY_Y_REMOVE || : 
     return { ...state, c: action.payload }; 
    default: 
     return state; 
    } 
};