web-dev-qa-db-fra.com

Quel est le moyen le plus rapide de modifier des objets immuables à l'aide d'opérateurs d'étalement et de déstructuration

Je recherche une fonction pure, pour modifier mon objet d'état immuable. L'état d'origine donné en paramètre doit rester intact. Ceci est particulièrement utile lorsque vous travaillez avec des frameworks tels que Redux et qu'il est beaucoup plus facile de travailler avec immuable object en javascript. D'autant plus que travailler avec l'opérateur de propagation d'objet avec Babel est déjà possible.

Je n'ai rien trouvé de mieux que de copier d'abord l'objet et d'assigner/supprimer la propriété que je veux comme ceci:

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

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

Je sens que ça pourrait être plus court

25
Tarion

Actions sur l'état, où l'état est considéré comme immuable.

Ajout ou mise à jour de la valeur d'une propriété :

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

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

Suppression d'une propriété  

// 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, ...state}) => state)(state);
}
59
Tarion

Une solution ES6, qui supporte un peu plus, est Object.assign :

const updateState = (state, item) => Object.assign({}, state, { [item.id]: item });
7
Ori Drori

Dans une fonction de la carte

Pour effectuer ce processus dans une fonction de la carte (supprimer un attribut et ajouter un nouvel attribut à chaque objet), à partir d'un tableau d'objets - 

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

Supprimez l'attribut keyToDelete et ajoutez une nouvelle clé newKey avec la valeur "someVar"

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

Mise à jour du tableau pour 

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

Voir cet article génial pour plus d'informations sur la méthode de suppression.

2
Aidan Ewen

Au lieu d'écrire du code passe-partout (comme indiqué ci-dessus: (({[id]: deleted, ...state}) => state)(state)) qui est difficile à lire, vous pouvez utiliser une bibliothèque pour faire de même:

Par exemple: 

import {remove} from 'immutable-modify'

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

Il prend également en charge les mises à jour imbriquées: 

import {set} from 'immutable-modify'

function updateState(state, item) {
   return set(state, 'user.products', (products) => ({
      ...products,
      items: products.items.concat(item),
      lastUpdate: Date.now()
   }))
}
0
user1444621