qual è il modo preferito per mutare uno stato di React?


97

Diciamo che ho un elenco di oggetti semplici nel mio this.state.listche posso utilizzare per visualizzare un elenco di bambini. Qual è allora il modo giusto per inserire l'oggetto this.state.list?

Di seguito è l'unico modo in cui penso che funzionerà perché non è possibile modificare this.statedirettamente come indicato nel documento.

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

Questo mi sembra brutto. C'è un modo migliore?


possibile duplicato della modifica corretta degli array di stato in ReactJS , richiesta di unione
Brigand

Tutte queste risposte riguardano l'aggiunta di un elemento a un array. Ma per quanto riguarda la rimozione di un elemento da esso? O semplicemente per ripristinare completamente l'array su uno nuovo?
Augustin Riedinger

Risposte:


165

concat restituisce un nuovo array, quindi puoi farlo

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

un'altra alternativa è l' aiutante dell'immutabilità di React

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

  this.setState(newState);

6
concataccetta un array, quindi ti consigliamo this.state.list.concat([newObject]).
Sophie Alpert

@ BenAlpert funziona per me in Chrome, stai dicendo che questo è un comportamento non standard?
Heap

6
@Heap Bene, se gli passi un non-array concatlo avvolgerai in un array, ma è meglio aggiungere l'array da solo per essere esplicito: se hai [[1,2], [3,4]]e vuoi aggiungere [5,6]come elemento successivo, devi fare .concat([[5,6]])altro finirà con [[1,2], [3,4], 5, 6].
Sophie Alpert

2
Per quanto apprezzi l'idea alla base degli helper dell'immutabilità (e potrei finire per usarli comunque), Array.concatsicuramente è meglio aggiungere un'altra libreria.
Shawn Erquhart

1
Chiamare this.setState con un valore derivato da this.state ti farà cadere in fallo di problemi di aggiornamento in batch. Vedi stackoverflow.com/a/41445812/1998186 che collega a un jsfiddle che mostra il problema che otterrai.
NealeU

40

setState () può essere chiamato con una funzione come parametro:

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

o in ES5:

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

2
@ Arian: React eseguirà le istruzioni di mutazione DOM richieste necessarie per rendere solo gli elementi appena aggiunti. Dato, ovviamente, che gli elementi aggiunti di recente non cambiano il modo in cui gli elementi precedenti vengono visualizzati.
Jose Browne

1
Questa è una risposta fantastica e sembra molto più pulita della concatenazione di array solo per eseguire una spinta, anche se questa è un'opinione immagino.
Matt Styles

2
@ Nyalab non dovresti racchiudere il corpo della funzione tra parentesi? Allo stato attuale nel tuo esempio, le parentesi graffe dopo la freccia grossa inizierebbero un blocco, non un oggetto. Qualcosa del genere:this.setState((state) => ({ list: state.list.push(newObj) }))
kumarharsh

3
Come funziona questo codice? il metodo push restituirà a NUMBER, che verrà impostato sulla listvariabile
kumarharsh

1
Potresti anche usare uno splat:this.setState((state) => ({ list: [...state.list, newObj] }))
amebe


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.