- React.js: Wprowadzenie do kursu od podstaw
- Poznaj React.js
- Pierwszy komponent w React.js
- Props czyli atrybuty w React.js
- Podział na komponenty w React.js
- Klasy jako komponenty React.js
- Interakcja z komponentami React.js
- Stan komponentów React.js
- State w React.js 2
- Metody cyklu życia komponentu w React.js
- React.js w przykładach: filtrowanie statycznej listy
- Tworzenie aplikacji React.js dzięki create-react-app
- React.js na GitHub Pages dzięki create-react-app
- Testowanie aplikacji React.js — podstawy Enzyme
- Testowanie React.js w Enzyme — props, state i interakcje
- Poprawne bindowanie funkcji w React.js
- Odpowiadam na pytania: Babel, ECMAScript, destrukturyzacja, onClick, className
- Komunikacja pomiędzy komponentami w React.js
- Komunikacja z API w React.js
- Formularze w React.js — kontrolowane komponenty
- Formularze w React.js — niekontrolowane komponenty
- Odpowiadam na pytania: props, nawiasy klamrowe, funkcje vs klasy, import react
- TDD w React.js z pomocą react-testing-library
- Flux i Redux: globalny store i jednokierunkowy przepływ danych
- React + Redux — kurs: wprowadzenie i podstawy
- React + Redux — filtrowanie listy, proste selektory
- Projektowanie komponentów: Presentational & Container Components
- Asynchroniczność w Redux: redux-thunk
- Kiedy używać state, a kiedy Redux?
- Nowe metody cyklu życia: getDerivedStateFromProps i getSnapshotBeforeUpdate
- Leniwe ładowanie komponentów w React dzięki import
- Higher Order Reducers — Redux i powtarzanie kodu
- React Hooks — wprowadzenie i motywacja
- React Hooks: useState, czyli stan w komponentach funkcyjnych
- React Hooks: useState — wiele stanów, callbacki i inne niuanse
- React Hooks: useEffect — efekty uboczne w komponencie
- React Hooks a żądania do API
- useReducer — przenoszenie logiki poza komponent
- useMemo, useCallback, czyli rozwiązanie problemów ze zmieniającymi się propsami
- Wady React Hooks
- React Hooks: Piszemy własne hooki!
Od wersji React 16.3 funkcje componentWillMount
, componentWillReceiveProps
i componentWillUpdate
zostają oznaczone jako deprecated. Pojawiają się też dwie nowe metody cyklu życia: getDerivedStateFromProps
i getSnapshotBeforeUpdate
. Co to dla nas oznacza? Do czego one służą? Jak ich używać?
Informacje o pozostałych lifecycle methods w React znajdziesz tutaj:
Co złego w starych metodach?
W React wprowadzony zostaje powoli Async Rendering — czyli asynchroniczne renderowanie aplikacji kawałek po kawałku przez silnik Reacta. Jest to jedna z przyczyn, dla których w React 17 usunięte zostaną 3 metody cyklu życia:
componentWillReceiveProps
componentWillMount
componentWillUpdate
Nawiasem mówiąc, często te funkcje były źle rozumiane i niewłaściwie wykorzystywane:
componentWillReceiveProps
Przykładowo, zamiast dobrej architektury komponentów, Single Responsibility Principle, podziału na komponenty prezentacyjne i kontenery, wiele osób wrzuca kilka odpowiedzialności do jednego komponentu, a na zmiany reaguje przez componentWillReceiveProps
. Niedobrze. Ta metoda powinna być wykorzystywana sporadycznie, tylko w rzadkich przypadkach. Często niestety widzę ją w użyciu do obsługi prostego przepływu danych w aplikacji.
componentWillMount
Bardzo powszechnym nieporozumieniem jest używanie tej metody do wykonywania zapytań do API! Wiele osób myśli, że asynchroniczne zapytanie wysłane wewnątrz funkcji componentWillMount
zdąży zwrócić dane zanim komponent się wyrenderuje. To jednak całkowite niezrozumienie działania Reacta. Komponent się wyrenderuje niezależnie od tego co zrobisz w componentWillMount
, a brak danych, na czas oczekiwania na nie, musisz obsłużyć w render
.
Dodatkowo, przy Async Rendering, React nie daje gwarancji, że wywoła tę funkcję tylko raz — może to zrobić wielokrotnie. Ponadto, do samego końca nie wiadomo czy do zamontowania komponentu naprawdę dojdzie — może się bowiem zdarzyć tak, że metoda componentWillMount
zostanie wywołana (kilka razy!), a następnie rendering zostanie przerwany (np. użytkownik kliknie „wstecz” w przeglądarce) — i tym sposobem komponent nigdy się nie zamontuje.
componentWillUpdate
Prawdę mówiąc nigdy nie użyłem tej metody. Ale z tego co słyszałem, są osoby, które używały jej do zapisywania na boku stanu w locie w reakcji na zmianę props
. Coooo? — powinnaś teraz zapytać. Dokładnie. To nie brzmi jak dobry pomysł.
Inne zastosowania to animacje i przygotowanie na zmiany w DOM.
Co się stanie ze starymi metodami?
Od React 16.3 zostają wprowadzone nowe metody, które docelowo zastąpią stare:
UNSAFE_componentWillReceiveProps
UNSAFE_componentWillMount
UNSAFE_componentWillUpdate
Jednocześnie istnieją też nadal metody z nazwami bez prefiksów — jak dotąd.
Od React 16.x (w bliskiej przyszłości) użycie metod bez prefiksu UNSAFE_
spowoduje wyświetlenie ostrzeżenia w konsoli.
Od React 17 stare metody zostaną usunięte całkowicie (tylko metody z UNSAFE_
będą dalej działać).
Prefiks UNSAFE_
ma zniechęcać do używania tych funkcji 😉 Mam nadzieję, że skutecznie!
Co zamiast?
Jednocześnie wprowadzone zostają 2 nowe funkcje:
getDerivedStateFromProps
getSnapshotBeforeUpdate
Mają one zastąpić stare metody i całkowicie pokryć zakres ich użycia. Po kolei:
getDerivedStateFromProps
Jest to metoda statyczna:
class MyComponent extends React.Component {
static getDerivedStateFromProps(props, state) {
// ...
}
}
Jest ona wywoływana po zainstancjonowaniu komponentu, a także po jakiejkolwiek zmianie propsów (technicznie rzecz biorąc zostanie ona wywołana zawsze przy przerenderowaniu rodzica, nawet gdy propsy się nie zmieniają). Dodatkowo, od wersji 16.4, wywoływana jest ona także zawsze przy zmianie state komponentu. Zadaniem tej funkcji jest zwrócić obiekt reprezentujący zmiany w state
, albo null
jeśli zmiany w state
nie są potrzebne.
getSnapshotBeforeUpdate
Ta metoda zostanie wywołana tuż przed przerenderowaniem komponentu. Służy ona do przechowania jakiegoś stanu (snapshota) na czas renderowania. Tenże „snapshot” będzie dostępny jako 3 argument w funkcji componentDidUpdate
już po przerenderowaniu:
class MyComponent extends React.Component {
getSnapshotBeforeUpdate(prevProps, prevState) {
// ...
}
componentDidUpdate(prevProps, prevState, snapshot) {
// ...
}
}
Co może być takim snapshotem? Aby Cię nakierować o jakie rzeczy chodzi: Np. pozycja scrolla w Twoim komponencie. Zapisujesz wysokość scrolla, komponent się przerenderowuje (i możliwe, że scroll się przesuwa lub jest gubiony bo zmienia się DOM), a następnie w componentDidUpdate
przywracasz pozycję scrolla.
Popularne przypadki użycia
Chciałbym tutaj krótko przedstawić popularne przypadki użycia starych metody i sposoby na zaimplementowanie ich z użyciem nowych.
Zapytania do API; subskrypcje
Wspomniałem, że wiele osób próbuje robić je w componentWillMount
z powodu braku zrozumienia działania tej metody. Zamiast tego wykorzystaj componentDidMount
. Tak samo wszelkie subskrypcje — i nie zapomnij ich usunąć w componentWillUnmount
!
class MyComponent extends React.Component {
componentDidMount() {
this.subscription = subscribe(this.onSubscriptionChange);
}
componentWillUnmount() {
this.subscription.cancel(); // !
}
}
Reagowanie na zmiany propsów
Załóżmy, że zawsze gdy zmieni się konkretny props, chcesz wyświetlić informację o tym użytkownikowi. Często realizowane przez funkcję componentWillReceiveProps
. Teraz użyj componentDidUpdate
. Początkowo może to nie być 100% intuicyjne, ale kod wszystko rozjaśnia:
class MyComponent extends React.Component {
componentDidUpdate(prevProps, prevState) {
if (this.props.notification !== prevProps.notification) {
displayNotification(this.props.notification);
}
}
}
Podobnie zaimplementujesz pobieranie danych z API po zmianie propsów. Sprawdź co się zmieniło i wykonaj zapytanie:
class MyComponent extends React.Component {
fetchData(id) {
if (this._asyncRequest) {
this._asyncRequest.cancel();
}
this._asyncRequest = someAsyncRequest(id);
}
componentDidUpdate(prevProps, prevState) {
if (this.props.id !== prevProps.id) {
this.fetchData(this.props.id);
}
}
componentDidMount() {
this.fetchData(this.props.id);
}
componentWillUnmount() {
this._asyncRequest.cancel();
}
}
Zmiana state po zmianie propsów
To właściwie wszystko co robi funkcja getDerivedStateFromProps
. Wyobraź sobie komponent, który dostaje listę userów jako props, a wewnątrznie może je jakoś filtrować (na podstawie słowa wpisanego w input — state.search
). Po zmianie propsów chcemy zapisać w state
przefiltrowanych użytkowników na podstawie obecnie wpisanego filtra:
class MyComponent extends React.Component {
static getDerivedStateFromProps(props, state) {
if (props.users !== state.users) {
return {
filteredUsers: filterUsers(props.users, state.search),
};
}
return null;
}
}
Podsumowanie
Mam nadzieję, że pomogłem Ci zaktualizować swoją wiedzę na temat metod cyklu życia w React. Poznaj React w dwa dni na szkoleniu Type of Web! Pamiętaj o tym tworząc kolejne komponenty i stopniowo refaktoruj te już istniejące. Jeśli są dobrze napisane to raczej nie będzie z tym problemu. Natomiast jeśli napotkasz gdzieś wspomniane tutaj metody — to zawsze sygnał ostrzegawczy — bardzo możliwe, że z danym komponentem jest coś nie tak 😉
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.
Więcej informacji: reactjs.org/blog/2018/03/27/update-on-async-rendering.html
- React.js: Wprowadzenie do kursu od podstaw
- Poznaj React.js
- Pierwszy komponent w React.js
- Props czyli atrybuty w React.js
- Podział na komponenty w React.js
- Klasy jako komponenty React.js
- Interakcja z komponentami React.js
- Stan komponentów React.js
- State w React.js 2
- Metody cyklu życia komponentu w React.js
- React.js w przykładach: filtrowanie statycznej listy
- Tworzenie aplikacji React.js dzięki create-react-app
- React.js na GitHub Pages dzięki create-react-app
- Testowanie aplikacji React.js — podstawy Enzyme
- Testowanie React.js w Enzyme — props, state i interakcje
- Poprawne bindowanie funkcji w React.js
- Odpowiadam na pytania: Babel, ECMAScript, destrukturyzacja, onClick, className
- Komunikacja pomiędzy komponentami w React.js
- Komunikacja z API w React.js
- Formularze w React.js — kontrolowane komponenty
- Formularze w React.js — niekontrolowane komponenty
- Odpowiadam na pytania: props, nawiasy klamrowe, funkcje vs klasy, import react
- TDD w React.js z pomocą react-testing-library
- Flux i Redux: globalny store i jednokierunkowy przepływ danych
- React + Redux — kurs: wprowadzenie i podstawy
- React + Redux — filtrowanie listy, proste selektory
- Projektowanie komponentów: Presentational & Container Components
- Asynchroniczność w Redux: redux-thunk
- Kiedy używać state, a kiedy Redux?
- Nowe metody cyklu życia: getDerivedStateFromProps i getSnapshotBeforeUpdate
- Leniwe ładowanie komponentów w React dzięki import
- Higher Order Reducers — Redux i powtarzanie kodu
- React Hooks — wprowadzenie i motywacja
- React Hooks: useState, czyli stan w komponentach funkcyjnych
- React Hooks: useState — wiele stanów, callbacki i inne niuanse
- React Hooks: useEffect — efekty uboczne w komponencie
- React Hooks a żądania do API
- useReducer — przenoszenie logiki poza komponent
- useMemo, useCallback, czyli rozwiązanie problemów ze zmieniającymi się propsami
- Wady React Hooks
- React Hooks: Piszemy własne hooki!
Super wpis, dzięki za wytłumaczenie!
Dzięki też za objaśnienie componentWillMount. Niestety do tej pory sam używałem tej metody nieprawidłowo (tak jak w podanym przykładzie).
Pozdrawiam.
Prawda jest taka, że tych metod opisanych tutaj powinno się w ogóle używać rzadko albo nigdy 🙂 To częsty błąd, mój także początkowo! 😀
Fajny wpis, mi się podoba! Jeśli zmienię state w getDerivedStateFromProps, bo zaszły jakieś zmiany w propsach, to komponent znów się wyrenderuje (po zmianie propsów od razu, a potem po zmianie state w getDerivedStateFromProps)? Chodzi mi o to, w jakim momencie komponent się renderuje?
Z tego co wiem to wyrenderuje się raz.
Ale to szczegół implementacyjny, to nie powinno mieć wpływu na działanie aplikacji.
[…] Nowe metody cyklu życia: getDerivedStateFromProps i getSnapshotBeforeUpdate […]