React Hooks: useState, czyli stan w komponentach funkcyjnych

wp-content/uploads/2017/10/React_logo_wordmark-300x101-1-e1508612391308.png
  1. Wprowadzenie do kursu React.js od podstaw
  2. Poznaj React.js
  3. Pierwszy komponent w React.js
  4. Props czyli atrybuty w React.js
  5. Podział na komponenty w React.js
  6. Klasy jako komponenty React.js
  7. Interakcja z komponentami React.js
  8. Stan komponentów React.js
  9. State w React.js 2
  10. Metody cyklu życia komponentu w React.js
  11. React.js w przykładach: filtrowanie statycznej listy
  12. Tworzenie aplikacji React.js dzięki create-react-app
  13. React.js na GitHub Pages dzięki create-react-app
  14. Testowanie aplikacji React.js — podstawy Enzyme
  15. Testowanie React.js w Enzyme — props, state i interakcje
  16. Poprawne bindowanie funkcji w React.js
  17. Odpowiadam na pytania: Babel, ECMAScript, destrukturyzacja, onClick, className
  18. Komunikacja pomiędzy komponentami w React.js
  19. Komunikacja z API w React.js
  20. Formularze w React.js — kontrolowane komponenty
  21. Formularze w React.js — niekontrolowane komponenty
  22. Odpowiadam na pytania: props, nawiasy klamrowe, funkcje vs klasy, import react
  23. TDD w React.js z pomocą react-testing-library
  24. Flux i Redux
  25. React + Redux — kurs: wprowadzenie i podstawy
  26. React + Redux — filtrowanie listy, proste selektory
  27. Projektowanie komponentów: Presentational & Container Components
  28. Asynchroniczność w Redux: redux-thunk
  29. Kiedy używać state, a kiedy Redux?
  30. Nowe metody cyklu życia: getDerivedStateFromProps i getSnapshotBeforeUpdate
  31. Leniwe ładowanie komponentów w React dzięki import
  32. Higher Order Reducers — Redux i powtarzanie kodu
  33. React Hooks — wprowadzenie i motywacja
  34. React Hooks: useState, czyli stan w komponentach funkcyjnych
  35. React Hooks: useState — wiele stanów, callbacki i inne niuanse
  36. React Hooks: useEffect — efekty uboczne w komponencie
  37. React Hooks a żądania do API
  38. useReducer — przenoszenie logiki poza komponent
  39. useMemo, useCallback, czyli rozwiązanie problemów ze zmieniającymi się propsami

Wbudowanych Hooków w React jest kilka, a jeszcze więcej możesz tworzyć sam(a). Zaczniemy jednak od podstawowego wbudowanego Hooka useState. Dodamy stan do komponentu funkcyjnego!

Komponenty funkcyjne

Na początek krótka informacja od twórców React. Do tej pory komponenty będące funkcjami nazywały się Stateless Functional Component. Od momentu wprowadzenia Hooków ta nazwa nie miałaby dłuższej sensu. Dlatego od teraz takie komponenty nazywamy Function Component.

useState — stan

Zgodnie z konwencją, nazwy React Hook zaczynają się od słowa use. Mamy więc useState, useEffect, useContext itd. W tym wpisie będę mówił tylko o tym pierwszym, kolejne wkrótce 🙂

Weźmy pierwszy najprostszy przykład z hookami: Dodanie stanu do komponentu funkcyjnego. Zróbmy licznik 😉

function App() {
  const [counter, setCounter] = React.useState(0);

  return (
    <div>
      {counter}
      <button onClick={() => setCounter(counter + 1)}>+</button>
    </div>
  );
};

Co tu się dzieje? Wywołuję funkcję React.useState(0);. Jest to Hook. Ten Hook zwraca tablicę z dwoma elementami:

  1. To stan
  2. To funkcja zmieniająca stan

Użyłem tutaj destrukturyzacji tablicy i nazwałem stan counter, a funkcję zmieniającą stan setCounter. Jest to zgodne z konwencją, ale w zasadzie te nazwy mogłyby być zupełnie dowolne.

Dodatkowo, warto zwrócić uwagę, że useState jako argument przyjmuje stan początkowy — w moim przypadku liczbę 0.

Stała counter zawiera aktualny stan. Na początku jest to stan początkowy, czyli 0. Jeśli wywołam funkcję setCounter(…) to stan zostanie zmieniony i w kolejnym renderze counter będzie zawierał nową wartość.

Sprawdźmy jak to działa w praktyce:

See the Pen React Hooks: Licznik by Michał Miszczyszyn (@mmiszy) on CodePen.

Ale co to w ogóle jest Hook?

Abstrakcyjnie: Hooki to mechanizm mocno inspirowany State Monad z Haskella. Pozwalają na przechowywanie stanu pomiędzy kolejnymi wywołaniami funkcji, bez konieczności martwienia się mutacjami czy jakimiś referencjami.

Jak to działa pod podszewką? W telegraficznych skrócie: React wywołuje Twoją funkcję (komponent funkcyjny) i może przechowywać sobie związany z nią stan. Przed wywołaniem komponentu funkcyjnego, React wie dokładnie, który komponent jest wywoływany i który stan powinien zostać „włożony” do Hooków. Po zakończeniu wywołania funkcji, React sprawdza czy stan się zmienił i odkłada na odpowiednie miejsce. React robi za Ciebie dokładnie to, co do tej pory było robione manualnie przez Ciebie w metodach cyklu życia. To ogromne ułatwienie!

Filtrowanie listy z Hookami

Wróćmy do przykładu, który był implementowany w tym kursie już 2 razy:

React.js w przykładach: filtrowanie statycznej listy

Zamiast używać klasy, setStatethis.state, użyj Hooka useState. Pomijam fragmenty, które się powtarzają w stosunku do starego kodu:

function App() {
  const [filteredUsers, setUsers] = React.useState(allUsers);

  function filterUsers(e) {
    const text = e.currentTarget.value;
    const filteredUsers = getFilteredUsersForText(text);
    setUsers(filteredUsers);
  }

  return (
    <div>
      <input onInput={filterUsers} />
      <UsersList users={filteredUsers} />
    </div>
  );
};

W momencie wpisania czegoś w input, wywoływana jest funkcja filterUsers, która filtruje listę i wywołuje setUsers pochodzące z Hooka. Ot, cała filozofia. Stan jest gdzieś przechowywany i nie bardzo obchodzi nas gdzie. To po prostu działa.

See the Pen React Hooks: Filtrowanie listy by Michał Miszczyszyn (@mmiszy) on CodePen.

Pytania?

Naucz się React na szkoleniu Type of Web! Jeśli chcesz na bieżąco śledzić kolejne części kursu React.js to koniecznie polub mnie na Facebooku i zapisz się na newsletter.

Ćwiczenie

Ćwiczenie: Przepisz jakiś komponent z klasy na Hooka useState. Jak wrażenia?

Nawigacja po kursie:
  1. Wprowadzenie do kursu React.js od podstaw
  2. Poznaj React.js
  3. Pierwszy komponent w React.js
  4. Props czyli atrybuty w React.js
  5. Podział na komponenty w React.js
  6. Klasy jako komponenty React.js
  7. Interakcja z komponentami React.js
  8. Stan komponentów React.js
  9. State w React.js 2
  10. Metody cyklu życia komponentu w React.js
  11. React.js w przykładach: filtrowanie statycznej listy
  12. Tworzenie aplikacji React.js dzięki create-react-app
  13. React.js na GitHub Pages dzięki create-react-app
  14. Testowanie aplikacji React.js — podstawy Enzyme
  15. Testowanie React.js w Enzyme — props, state i interakcje
  16. Poprawne bindowanie funkcji w React.js
  17. Odpowiadam na pytania: Babel, ECMAScript, destrukturyzacja, onClick, className
  18. Komunikacja pomiędzy komponentami w React.js
  19. Komunikacja z API w React.js
  20. Formularze w React.js — kontrolowane komponenty
  21. Formularze w React.js — niekontrolowane komponenty
  22. Odpowiadam na pytania: props, nawiasy klamrowe, funkcje vs klasy, import react
  23. TDD w React.js z pomocą react-testing-library
  24. Flux i Redux
  25. React + Redux — kurs: wprowadzenie i podstawy
  26. React + Redux — filtrowanie listy, proste selektory
  27. Projektowanie komponentów: Presentational & Container Components
  28. Asynchroniczność w Redux: redux-thunk
  29. Kiedy używać state, a kiedy Redux?
  30. Nowe metody cyklu życia: getDerivedStateFromProps i getSnapshotBeforeUpdate
  31. Leniwe ładowanie komponentów w React dzięki import
  32. Higher Order Reducers — Redux i powtarzanie kodu
  33. React Hooks — wprowadzenie i motywacja
  34. React Hooks: useState, czyli stan w komponentach funkcyjnych
  35. React Hooks: useState — wiele stanów, callbacki i inne niuanse
  36. React Hooks: useEffect — efekty uboczne w komponencie
  37. React Hooks a żądania do API
  38. useReducer — przenoszenie logiki poza komponent
  39. useMemo, useCallback, czyli rozwiązanie problemów ze zmieniającymi się propsami