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 nimsuper(props)
na samym początku; możesz też tam ustawićthis.state = {…}
bez konieczności używaniasetState
. To będzie początkowy stan aplikacji. Inne operacje (efekty uboczne, subskrypcje) powinny się znaleźć wcomponentDidMount
componentWillMount()
— wywoływany tuż przed zamontowaniem komponentu; ta metoda raczej Ci się nie przydarender()
— 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 wcomponentWillUnmount()
!)
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
znextProps
i sprawdzić czy rzeczywiście coś się zmieniło (bo nie zawsze musi…)shouldComponentUpdate(nextProps, nextState)
— wywoływana zawsze przedrender()
; jeśli z tej funkcji zwróciszfalse
torender()
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ę ichstate
, a w przyszłości React będzie traktował funkcjęshouldComponentUpdate()
tylko jako wskazówkę, a nie wyznacznik — wrócę do tego tematu jeszczecomponentWillUpdate(nextProps, nextState)
— wywoływana tuż przedrender()
— pamiętaj aby nie modyfikowaćstate
wewnątrz tej funkcjirender()
— 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 stanucomponentDidMount()
— 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>
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:
Rodzic pozwala na ustawienie (input
+button
+onClick
+setState
) jakiejś wartości liczbowej i przekazuje ją do dziecka jako props.Dziecko ma początkowo wyświetlać liczbę podaną od rodzica, a dodatkowo ma umożliwiać zwiększanie i zmniejszanie tej liczby (button
+onClick
+setState
).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:
- Rodzic pozwala na ustawienie w inpucie jakiejś wartości liczbowej i przekazuje ją do dziecka.
- Dziecko ma początkowo wyświetlać liczbę podaną od rodzica, a dodatkowo ma umożliwiać zwiększanie i zmniejszanie tej liczby.
- W momencie, gdy rodzic ustawi liczbę, dziecko powinno zresetować swój stan do podanej liczby.
- 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ę!