Skocz do treści

Już wkrótce odpalamy zapisy na drugą edycję next13masters.pl. Zapisz się na listę oczekujących!

State w React.js 2

Pod koniec poprzedniego wpisu zadałem podchwytliwe ćwiczenie dotyczące state w React.js. Jeśli jeszcze go nie wykonałaś/eś to teraz jest ten moment, aby wrócić i spróbować ;) W tym wpisie rozwijam temat state, opisuję dokładniej jak działa setState i jakie argumenty przyjmuje.

Ten artykuł jest częścią 9 z 42 w serii React.js.

Zdjęcie Michał Miszczyszyn
JavaScript42 komentarze

Zacznijmy może od wykonania ćwiczenia z poprzedniego wpisu. Zadanie brzmiało tak:

Dodaj dwa nowe liczniki. Pierwszy, który będzie zliczał wszystkie kliknięcia w przyciski (tzn. kliknięcie w + i - daje 0 na obecnym liczniku oraz 2 na nowym liczniku), oraz drugi, który będzie zliczał podwójne kliknięcia (tzw. double click) na elemencie z wynikiem.

Wydaje się proste, ale implementacja odkrywa przez Tobą pewien ważny szczegół dotyczący działania funkcji setState. W jaki sposób chcielibyśmy tutaj aktualizować stan? Musimy przechowywać jeden licznik z sumą, drugi zliczający łączne kliknięcia oraz trzeci, który będzie przechowywał podwójne kliknięcia. To co jest tutaj istotne to fakt, że w momencie pojedynczego kliknięcia aktualizujesz tylko dwa liczniki, a trzeci pozostaje bez zmian. Jak to najprościej zaimplementować?

Jak działa setState?

increment() {
    this.setState({
      sumCount: this.state.counter + 1
      totalCount: this.state.totalCount + 1
      doubleClickCount: this.state.dblClickCount
    })
  }

Działa, po prostu do doubleClickCount zawsze przypisana zostaje niezmieniona wartość this.state.doubleClickCount. Ale czy to konieczne? Co by było, gdyby stan komponentu składał się nie z 3, a z 15 pól? Nie dyskutujmy teraz czy to dobre rozwiązanie, tylko zastanów się jak by musiała wyglądać każda aktualizacja stanu… właśnie.

Na szczęście setState jest mądrzejsze i automatycznie łączy obecny stan z tym podanym mu jako argument — i nadpisuje tylko podane własności. To co się nie zmienia pomijasz:

increment() {
    this.setState({ // doubleClickCount pozostanie niezmienne
      sumCount: this.state.counter + 1
      totalCount: this.state.totalCount + 1
    })
  }

A tutaj w pełni działające rozwiązanie:

Zobacz Codepen Stan komponentów React.js.

Jeśli to nie jest dla Ciebie jasne, nie ma w tym nic złego :) Możesz zadać nam pytanie w komentarzu! zapisz się na szkolenie z React.

Funkcja przekazana do setState

Widzisz, że do setState możemy po prostu przekazać obiekt, który zostanie połączony z obecnym stanem i nadpisze podane własności. I to, do niedawna, była jedyna opcja. Od Reacta 16 polecanym sposobem aktualizowania stanu jest przekazanie do setState funkcji, a nie obiektu. Taka funkcja to tzw. updater. Jak to działa? Updater to taka funkcja, która jako argument przyjmuje obecny stan i jako wynik zwraca obiekt, który zostanie połączony z istniejącym stanem. Przykładowo dla nas:

  increment() {
    this.setState(prevState => {
      return {
        sumCount: prevState.sumCount + 1,
        totalCount: prevState.totalCount + 1
      };
    });
  }

Jakie są zalety tego rozwiązania względem po prostu przekazania obiektu do setState? W tym przypadku żadne. setState jest asynchroniczne (o tym zaraz) i sprawia problemy, gdy wywołamy je kilka razy pod rząd — tutaj pomoże nam updater. Dodatkowo, updater pomaga poprawić wydajność aplikacji — jeśli w updaterze zwrócisz null to nie zostanie wykonany ponowny render. Poświęcę temu wszystkiemu inny wpis!

setState i callback

Dokładnie tak jak w nagłówku. Co to oznacza? Najprościej mówiąc, że wywołanie setState nie zmienia stanu od razu, tylko dopiero po jakimś czasie. Czyli, przykładowo, próba odczytania stanu od razu po jego zmianie przez setState pokaże nam nadal stary, nieaktualny stan. Otwórz konsolę i kliknij w przycisk w tym przykładzie:

Zobacz Codepen Stan komponentów React.js.

Jak naprawić ten problem? Otóż setState przyjmuje też drugi argument: callback. Jeśli jako drugi argument przekażesz funkcję to zostanie ona wywołana w momencie, gdy stan będzie już zaktualizowany. Spójrz po prostu na przykład (z widoczną konsolą):

Zobacz Codepen Stan komponentów React.js.

Jeśli chcesz na bieżąco dowiadywać się o kolejnych częściach kursu React.js to koniecznie śledź mnie na Facebooku i zapisz się na newsletter.

Ćwiczenie

Ćwiczenie: Napisz komponent, który będzie miał dwa inputy na imię i nazwisko. Obok, powinien się wyświetlać tekst wpisany w te pola (imię nazwisko). Użyj do tego atrybutu onInput oraz funkcji setState.

Napisz w komentarzu jak Ci się podoba obsługa formularzy w React. Poświęcę temu jeden z kolejnych odcinków, więc chcę wiedzieć już teraz jakie masz uwagi :)

👉  Znalazłeś/aś błąd?  👈Edytuj ten wpis na GitHubie!

Autor