jaki jest preferowany sposób mutowania stanu React?


97

Powiedzmy, że mam listę zwykłych obiektów this.state.list, których mogę następnie użyć do renderowania listy dzieci. Jaki jest zatem właściwy sposób wstawiania obiektu this.state.list?

Poniżej znajduje się jedyny sposób, w jaki myślę, że zadziała, ponieważ nie możesz this.statebezpośrednio mutować, jak wspomniano w dokumencie.

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

Wydaje mi się to brzydkie. Czy jest lepszy sposób?


możliwy duplikat Poprawna modyfikacja tablic stanów w ReactJS , prośba o scalenie
Brigand

Wszystkie te odpowiedzi dotyczą dodawania elementu do tablicy. Ale co z usunięciem z niego elementu? Lub po prostu całkowicie zresetować macierz do nowej?
Augustin Riedinger

Odpowiedzi:


165

concat zwraca nową tablicę, więc możesz to zrobić

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

inną alternatywą jest pomocnik niezmienności Reacta

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

  this.setState(newState);

6
concatprzyjmuje tablicę, więc będziesz chciał this.state.list.concat([newObject]).
Sophie Alpert

@BenAlpert działa u mnie w przeglądarce Chrome, czy mówisz, że to niestandardowe zachowanie?
Sterta

6
@Heap Cóż, jeśli przekażesz do niej nie-tablicę, zawinie concatją w tablicę, ale lepiej jest dodać tablicę samodzielnie, aby była wyraźna: jeśli masz [[1,2], [3,4]]i chcesz dodać [5,6]jako następny element, musisz zrobić .concat([[5,6]])inaczej skończę z [[1,2], [3,4], 5, 6].
Sophie Alpert

2
O ile doceniam ideę pomocników niezmienności (i może i tak z niej skorzystam), z Array.concatpewnością przebija dodanie kolejnej biblioteki.
Shawn Erquhart

1
Wywołanie this.setState z wartością pochodzącą z this.state spowoduje, że narazisz się na problemy z grupowaniem aktualizacji. Zobacz stackoverflow.com/a/41445812/1998186, który prowadzi do pliku jsfiddle pokazującego napotkany problem.
NealeU,

40

setState () można wywołać z funkcją jako parametrem:

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

lub w ES5:

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

2
@Arian: React wykona wymagane instrukcje mutacji DOM niezbędne do renderowania tylko nowo dodanych elementów. Zakładając oczywiście, że nowo dodane elementy nie zmieniają sposobu renderowania poprzednich elementów.
Jose Browne

1
To fantastyczna odpowiedź i wydaje się o wiele czystsza niż łączenie tablicy tylko po to, aby wykonać wypchnięcie, chociaż wydaje mi się, że to opinia.
Matt Styles

2
@Nyalab nie powinieneś zawijać treści funkcji w nawiasach? Tak jak teraz w twoim przykładzie, nawiasy klamrowe po grubej strzałce rozpoczęłyby blok, a nie obiekt. Coś takiego:this.setState((state) => ({ list: state.list.push(newObj) }))
kumarharsh

3
Jak działa ten kod? metoda push zwróci a NUMBER, które zostanie ustawione na listzmiennej
kumarharsh

1
Możesz również użyć this.setState((state) => ({ list: [...state.list, newObj] }))
ikony


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.