Quelle est la méthode préférée pour muter un état React?


97

Disons que j'ai une liste d'objets simples dans mon this.state.listque je peux ensuite utiliser pour rendre une liste d'enfants. Quelle est alors la bonne façon d'insérer un objet dans this.state.list?

Voici la seule façon dont je pense que cela fonctionnera car vous ne pouvez pas muter this.statedirectement le comme mentionné dans la doc.

this._list.push(newObject):
this.setState({list: this._list});

Cela me semble moche. Y a-t-il un meilleur moyen?


duplication possible de la modification correcte des tableaux d'états dans ReactJS , demandant la fusion
Brigand

Toutes ces réponses concernent l'ajout d'un élément à un tableau. Mais qu'en est-il de la suppression d'un élément? Ou simplement pour réinitialiser complètement le tableau à un nouveau?
Augustin Riedinger

Réponses:


165

concat renvoie un nouveau tableau, donc vous pouvez faire

this.setState({list: this.state.list.concat([newObject])});

une autre alternative est l' assistant d'immuabilité de React

  var newState = React.addons.update(this.state, {
      list : {
        $push : [newObject]
      }
  });

  this.setState(newState);

6
concatprend un tableau, donc vous voudrez this.state.list.concat([newObject]).
Sophie Alpert

@BenAlpert fonctionne pour moi dans Chrome, dites-vous qu'il s'agit d'un comportement non standard?
Heap

6
@Heap Eh bien, si vous lui passez un non-tableau, concatil l'enveloppera dans un tableau, mais il est préférable d'ajouter le tableau vous-même pour être explicite: si vous avez [[1,2], [3,4]]et voulez ajouter [5,6]comme élément suivant, vous devez faire .concat([[5,6]])autre chose va finir avec [[1,2], [3,4], 5, 6].
Sophie Alpert

2
Autant j'apprécie l'idée derrière les aides à l'immuabilité (et je peux finir par l'utiliser de toute façon), autant il Array.concatvaut mieux ajouter une autre bibliothèque.
Shawn Erquhart le

1
L'appel de this.setState avec une valeur dérivée de this.state vous fera tomber sous le coup des problèmes de mise à jour par lots. Voir stackoverflow.com/a/41445812/1998186 qui renvoie à un jsfiddle montrant le problème que vous rencontrez.
NealeU

40

setState () peut être appelé avec une fonction comme paramètre:

this.setState((state) => ({ list: state.list.concat(newObj) }))

ou dans ES5:

this.setState(function(state) {
  return {
   list: state.list.concat(newObj)
  }
})

2
@Arian: React exécutera les instructions de mutation DOM requises pour rendre uniquement les éléments nouvellement ajoutés. Étant donné que vous êtes des éléments nouvellement ajoutés, cela ne change pas le rendu des éléments précédents.
Jose Browne

1
C'est une réponse fantastique et se sent tellement plus propre que le tableau concatant juste pour effectuer une poussée, même si c'est l'opinion que je suppose.
Matt Styles

2
@Nyalab ne devriez-vous pas mettre le corps de la fonction entre parenthèses? Dans l'état actuel de votre exemple, les accolades après la grosse flèche commenceraient un bloc, pas un objet. Quelque chose comme ça:this.setState((state) => ({ list: state.list.push(newObj) }))
kumarharsh

3
Comment fonctionne ce code? la méthode push retournera a NUMBER, qui sera défini sur la listvariable
kumarharsh

1
Vous pouvez également utiliser un splat:this.setState((state) => ({ list: [...state.list, newObj] }))
amoebe


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.