Skocz do treści

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

Metody cyklu życia komponentu w React.js

Przy okazji omawiania komponentów będących klasami w React.js, wspomniałem też o możliwości korzystania z metod cyklu życia (lifecycle methods). Chciałbym do tego tematu teraz powrócić. Pokażę jakie metody cyklu życia definiuje React.js, do czego one służą i kiedy mogą się przydać.

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

Zdjęcie Michał Miszczyszyn
JavaScript74 komentarze

Cykl życia komponentu

Bardzo dokładnie omawiamy cykl życia komponentów na szkoleniach. zapisz się na szkolenie z React.

Każdy komponent ma pewien określony cykl życia. Na odpowiednich etapach wywoływane są też jego metody cyklu życia. Możemy je podzielić ogólnie na dwie grupy:

  • z nazwami zaczynającymi się od will — wywoływane zanim się coś wydarzy
  • z nazwami zaczynającymi się od did — wywoływane po tym jak coś się zdarzyło

Oto kolejne etapy życia komponentów:

Montowanie

Komponent jest tworzony i dodawany do drzewa Dom.

  • constructor(props) — jeśli definiujesz konstruktor to nie zapomnij wywołać w nim super(props) na samym początku; możesz też tam ustawić this.state = {…} bez konieczności używania setState. To będzie początkowy stan aplikacji. Inne operacje (efekty uboczne, subskrypcje) powinny się znaleźć w componentDidMount
  • componentWillMount() — wywoływany tuż przed zamontowaniem komponentu; ta metoda raczej Ci się nie przyda
  • render() — funkcja, która powinna zwrócić jeden z możliwych wyników:
    • element (JSX)
    • tablicę elementów (JSX)
    • string lub liczbę
    • null (nic się nie renderuje)
    • boolean (nic się nie renderuje)
    • Portal (stworzony przez ReactDOM.createPortal(…))
  • componentDidMount() — wywoływana po zamontowaniu komponentu; to dobre miejsce na jakiekolwiek funkcje polegające na DOM lub na subskrypcje (nie zapomnij o usunięciu subskrypcji w componentWillUnmount()!)

Aktualizacja

Update może zostać wywołany gdy zmieniają się props lub state.

  • componentWillReceiveProps(nextProps) — wywoływana m.in. gdy zmieniają się propsy (np. gdy element-rodzic je zmienia); warto porównać this.props z nextProps i sprawdzić czy rzeczywiście coś się zmieniło (bo nie zawsze musi…)
  • shouldComponentUpdate(nextProps, nextState) — wywoływana zawsze przed render(); jeśli z tej funkcji zwrócisz false to render() nie zostanie wykonany, a widok się raczej nie przerenderuje — można to wykorzystać do optymalizowania aplikacji; UWAGA: komponenty-dzieci nadal mogą się przerenderować np. gdy zmieni się ich state, a w przyszłości React będzie traktował funkcję  shouldComponentUpdate() tylko jako wskazówkę, a nie wyznacznik — wrócę do tego tematu jeszcze
  • componentWillUpdate(nextProps, nextState) — wywoływana tuż przed render() — pamiętaj aby nie modyfikować state wewnątrz tej funkcji
  • render() — j.w.
  • componentDidUpdate(prevProps, prevState) — wywoływana od razu po renderze; dobre miejsce na zmiany w DOM (jeśli takowe są potrzebne)

Odmontowanie

Wywoływane gdy komponent jest usuwany z DOM

  • componentWillUnmount() — wywoływana przed usunięciem komponentu z DOM; dobre miejsce na „posprzątanie” po sobie — usunięcie timerów, subskrypcji, zmian w DOM itd.

Łapanie błędów

  • componentDidCatch(error, info) — wywoływana gdy pojawi się błąd w czasie renderowania, wywoływania metod cyklu życia lub w konstruktorze — zagnieżdżonych komponentów; błędy w samym komponencie nie są tutaj łapane (zostaną złapane w komponencie-rodzicu)

Przykład

Oto prosta aplikacja, która pokazuje ważny przykład używania metod cyklu życia. Są to dwa komponenty, App odpowiada za pokazywanie i ukrywanie (po kliknięciu w przycisk) drugiego komponentu. Drugi komponent to Date, który co sekundę aktualizuje stan i wyświetla aktualną datę i godzinę. Wykorzystane zostały takie lifecycle methods:

  • constructor() — ustawianie początkowego stanu
  • componentDidMount() — rozpoczęcie odliczania (setInterval)
  • componentWillUnmount() — usunięcie odliczania (clearInterval)

Warto też zwrócić uwagę na sposób w jaki komponent App renderuje komponent Date w zależności od this.state.dateVisible:

<div>
  {this.state.dateVisible && <DateComponent />}
</div>
Zobacz Codepen Metody cyklu życia komponentu w React.js.

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: Stwórz dwa komponenty (rodzic i dziecko). Oto wymagania:

  1. Rodzic pozwala na ustawienie (input + button + onClick+ setState) jakiejś wartości liczbowej i przekazuje ją do dziecka jako props.
  2. Dziecko ma początkowo wyświetlać liczbę podaną od rodzica, a dodatkowo ma umożliwiać zwiększanie i zmniejszanie tej liczby (button + onClick + setState).
  3. W momencie gdy rodzic ustawi liczbę, dziecko powinno zresetować swój stan do podanej liczby (componentWillReceiveProps).

Aktualizacja 11.02.2019 r.: Przekreśliłem zadania powyżej. Miały one wyłącznie charakter dydaktyczny w celu poznania metody cyklu życia componentWillReceiveProps, ale wiele osób bardzo je sobie zapamiętało i stosowało podobny wzorzec w swoich aplikacjach. Poza tym React oznaczył tę metodę jako przestarzałą i niezalecaną. Zajrzyj do tego wpisu:

https://typeofweb.com/nowe-metody-cyklu-zycia-getderivedstatefromprops-i-getsnapshotbeforeupdate/

Sugerowane tutaj przeze mnie rozwiązanie było błędne. Prawidłowym rozwiązaniem problemu powyżej jest przeniesienie stanu dziecka wyżej — do rodzica (tzw. lifting state up). W ten sposób rodzic kontroluje stan obu inputów, a dziecko informuje go o zmianach, które chce wprowadzić. Dzięki temu unika się kilku częstych problemów: z rerenderem (który mógłby prowadzić do skasowania się wartości z inputów), z koniecznością wykrywania zmian (przez niezalecany componentWillReceiveProps), czy choćby z niejasnym przepływem danych (dane do dziecka od rodzica spływają w dół, ale tylko czasem… a dziecko nigdy nie informuje rodzica o zmianach — to niedobrze!). Oto zaktualizowana treść ćwiczenia:

Zaktualizowane ćwiczenie

Ćwiczenie: Stwórz dwa komponenty (rodzic i dziecko). Oto wymagania:

  1. Rodzic pozwala na ustawienie w inpucie jakiejś wartości liczbowej i przekazuje ją do dziecka.
  2. Dziecko ma początkowo wyświetlać liczbę podaną od rodzica, a dodatkowo ma umożliwiać zwiększanie i zmniejszanie tej liczby.
  3. W momencie, gdy rodzic ustawi liczbę, dziecko powinno zresetować swój stan do podanej liczby.
  4. Podpowiedź: Zastosuj tutaj lifting state up i stan obu komponentów trzymaj w rodzicu.

Napisz w komentarzu czy się udało. A jeśli masz jakieś wątpliwości albo nawet nie wiesz jak zacząć — odezwij się! Pomogę!

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

Autor