What is the shortest way to modify immutable objec

2020-05-14 08:32发布

I'm looking for a pure function, to modify my immutable state object. The original state given as parameter must stay untouched. This is especially useful when working with frameworks like Redux and makes working with immutable object in javascript much easier. Especially since working with the object spread operator using Babel is already possible.

I did not found anything better than first copy the object, and than assign/delete the property I want like this:

function updateState(state, item) {
  newState = {...state};
  newState[item.id] = item;
  return newState;
}

function deleteProperty(state, id) {
    var newState = {...state};
    delete newState[id];
    return newState;
}

I feel like it could be shorter

6条回答
Explosion°爆炸
2楼-- · 2020-05-14 08:34

Try:

const { id, ...noId } = state;

And test:

console.log(noId);
查看更多
欢心
3楼-- · 2020-05-14 08:42

In a Map Function

To do this process within a map function (remove an attribute and add a new attribute on each object), given an array of objects -

const myArrayOfObjects = [
    {id: 1, keyToDelete: 'nonsense'},
    {id: 2, keyToDelete: 'rubbish'}
];

Delete the attribute keyToDelete, and add a new key newKey with the value "someVar".

myArrayOfObjects.map(({ keyToDelete, ...item}) => { ...item, newKey:'someVar'});

Updating the array to

[
    {id: 1, newKey:'someVar'},
    {id: 2, newKey:'someVar'}
]

See this great post for more information on the deletion method.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2020-05-14 08:43

Instead of writing boilerplate code (as answered above: (({[id]: deleted, ...state}) => state)(state)) which is hard to read, you could use some library to do the same:

For example:

import {remove} from 'immutable-modify'

function updateState(state, item) {
   return remove(state, item.id)
}

It's also supports any nested updates:

import {set} from 'immutable-modify'

function updateState(state, item) {
   return set(state, 'user.products', (products) => ({
      ...products,
      items: products.items.concat(item),
      lastUpdate: Date.now()
   }))
}
查看更多
做个烂人
5楼-- · 2020-05-14 08:43

Removing item from an array, just use filter ;)

CASE 'REMOVE_ITEM_SUCCESS':

      let items = state.items.filter(element => element._id !== action.id);

      return {
            ...state, 
            items
      }
查看更多
老娘就宠你
6楼-- · 2020-05-14 08:51

Actions on state, where state is considered immutable.

Adding or Updating the value of a property:

// ES6:
function updateState(state, item) {
    return Object.assign({}, state, {[item.id]: item});
}

// With Object Spread:
function updateState(state, item) {
  return {
     ...state,
     [item.id]: item
  };
}

Deleting a property

// ES6:
function deleteProperty(state, id) {
    var newState = Object.assign({}, state);
    delete newState[id];
    return newState; 
}

// With Object Spread:
function deleteProperty(state, id) {
    let  {[id]: deleted, ...newState} = state;
    return newState;
}

// Or even shorter as helper function:
function deleteProperty({[id]: deleted, ...newState}, id) {
    return newState;
}

// Or inline:
function deleteProperty(state, id) {
    return (({[id]: deleted, ...newState}) => newState)(state);
}
查看更多
▲ chillily
7楼-- · 2020-05-14 08:51

An ES6 solution, that has a bit more support is Object.assign:

const updateState = (state, item) => Object.assign({}, state, { [item.id]: item });
查看更多
登录 后发表回答