- 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!
Jakiś czas temu zrobiło się głośno na temat React Hooks. Co to jest i po co Ci to? Przez dłuższy czas celowo nie pisałem o tym na blogu, gdyż była to ledwie propozycja i to do tego mocno niestabilna. Teraz jednak sytuacja się zmieniła i wszystko wskazuje na to, że React Hooks wkrótce trafią do wersji stabilnej. Czas się zaprzyjaźnić! Dlatego powstał kurs React Hooks.
Stan w komponentach funkcyjnych
Bolączką komponentów funkcyjnych było to, że były one bezstanowe. Tzn. działały idealnie do renderowania treści na podstawie propsów, jednak same nie mogły zawierać state
. Aby dodać stan, trzeba było taki komponent zrefaktorować na klasę — z tego powodu wiele osób zalecało po prostu zawsze używać klas i ignorować komponenty funkcyjne zupełnie. Hooki całkowicie zmieniają tę sytuację.
Motywacja dla powstania React Hooks
Jednak dodanie alternatywnej składni to tak naprawdę nie jest motywacja twórców Reacta. Po co alternatywna składnia, skoro miałaby ona niczego de facto nie zmieniać? Są lepsze powody dla istnienia Hooków.
Tworzenie uniwersalnej logiki zawierającej stan
Tworzenie takiej logiki, którą można by ponownie wykorzystać w różnych komponentach, a która zawiera także stan. To właśnie do rozwiązania tego problemu powstały takie wzorce jak Higher Order Components czy Render Props. Te jednak przyniosły kolejne kłopoty… Hooki zdają się wszystko rozwiązywać i upraszczać.
Uproszczenie kodu komponentów stanowych dzięki React Hooks
Przyjrzyjmy się typowemu komponentowi stanowemu. Warto pamiętać, kiedy używać stanu lokalnego w React. Żeby było ciekawiej, komponent ten podpina się pod subskrypcję danych (np. observable — temat mi bliski bo stworzyłem bibliotekę react-with-observable
). Przy odmontowywaniu musi tę subskrypcję oczywiście usunąć, a w przypadku zmian pamiętać o aktualizacji…
class MyComponent extends React.Component {
componentDidMount() {
this.subscribe();
}
componentWillUnmount() {
this.unsubscribe();
}
subscribe() {
this._unsubscribe = this.props.observable.subscribe(…);
}
unsubscribe() {
if (this._unsubscribe) {
this._unsubscribe();
}
}
componentDidUpdate(prevProps) {
if (prevProps.observable !== this.props.observable) {
this.unsubscribe();
this.subscribe();
}
}
render() {
// …
}
}
(kod wzorowany na tweecie @jamiebuilds)
WOAH, to całkiem sporo kodu jak na prostą subskrypcję, mam rację? I tyle rzeczy, o których trzeba pamiętać… A do tego nie ma żadnego sposobu, aby z tej logiki móc skorzystać ponownie w innym komponencie!
Powiązana logika jest… porozrzucana
Często, szczególnie w bardziej rozbudowanych komponentach, logika związana z tą samą rzeczą jest porozrzucana po różnych metodach cyklu życia. Jest to widoczne już w powyższym przykładzie, a ta klasa jeszcze tak naprawdę nic nie robi!
Statyczna analiza i minifikacja kodu
Okazuje się, że JS-owe klasy nie są czymś co można łatwo minifikować albo analizować statycznie. Każda tworzona metoda może być zarówno publiczna, jak i prywatna — nie ma sposobu, by to wiedzieć! Z tego powodu niemożliwa jest minifikacja nazw metod — nie wiadomo przecież czy danej funkcji ktoś/coś nie wywołuje też z zewnątrz klasy.
Dodajmy do tego problemy z nierozumieniem działania this
w JS przez wiele osób i wynikającą z tego konieczność bindowania metod, albo używania eksperymentalnej składni i pamiętania o wykorzystywaniu funkcji strzałkowych i jakiegoś transpilatora typu Babel… Ałć!
Problemy, które rozwiązują React Hooks
Jak powyższe problemy rozwiązują React Hooks?
- Fragmenty logiki zawierającej stan są zamykane w funkcjach, z których można korzystać w wielu komponentach.
- Same komponenty stają się funkcjami, co mocno upraszcza pracę z nimi.
- Kod wewnątrz funkcji jest łatwy do optymalnej minifikacji.
- Powiązana logika jest blisko siebie, a nie porozrzucana.
Brzmi dobrze? Do tego bez wątpienia Hooki są łatwiejsze i bardziej przystępne dla początkujących. Czyżby to strzał w 10? Moim zdaniem tak i dlatego napisałem ten kurs React Hooks!
Porównanie kodu z Hookami i bez nich
Spójrz na klasę z początku wpisu. Niemal dokładnie ten sam kod z użyciem React Hooks jest nie tylko krótki, ale też prosty:
function MyComponent(props) {
useEffect(() => {
return props.observable.subscribe(…);
}, [props.observable]);
// …
}
Rzuć też okiem na inne porównania. Kilka subskrypcji w jednym komponencie:
Minifikacja:
(źródło: twitter.com/jamiebuilds/status/1055988893303037952)
I wreszcie, związane ze sobą fragmenty kodu porozrzucane w klasie i uporządkowane blisko siebie w funkcji z Hookami:
Took @dan_abramov's code from #ReactConf2018 and visualised it so you could see the benefits that React Hooks bring us. pic.twitter.com/dKyOQsG0Gd
— Pavel Prichodko (@prchdk) October 29, 2018
Czy to Cię przekonuje? Mnie absolutnie tak.
Jeśli chcesz na bieżąco dowiadywać się o kolejnych częściach kursu React.js Hooks to koniecznie śledź mnie na Facebooku i zapisz się na newsletter.
Chcę nauczyć się Hooków!
Świetnie! Szczęśliwie się składa, że właśnie pracuję nad kolejną częścią kursu React Hooks 😉 Jeśli jednak bardzo Ci się spieszy to zajrzyj tutaj: Naucz się React na szkoleniu Type of Web!
- 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!
Pewnie w którymś momencie przekonam się do Hooków (a nawet pewnie nie będzie wyjścia), ale jak na razie średnio mnie to przekonuje. 1. Zawsze mówiono i uczono, że funkcja ma robić tylko jedną rzecz, a tu przetrzymywanie stanu, zmiana stanu, logiki, renderowanie ma się zawierać w funkcji? No to już jak dla mnie coś jest nie tak. 2. Wiadomo, super, że piszemy mniej kodu i w bundle’u również tego kodu jest o wiele mniej, ale dla mnie metody cyklu życia były mega czytelne i mówiły bardzo dużo o komponencie, a teraz wszystko ukryte tak naprawdę pod hookiem. W tym przykładzie ładnie to wygląda jak mamy taki malutki komponent, ale czy na pewno „funkcja hookowa” będzie czytelna przy większej ilości logiki itp? Co o tym sądzisz Michał? 🙂 P.S. oczywiście czekam na kurs Hooków 😀
1. Ale dokładnie to teraz robią klasy — robią wszystko. Dzięki Hookom będziesz mógł to wreszcie wydzielić na różne funkcje, których na dodatek będziesz mógł używać w wielu miejscach.
2. Dla mnie lifecycle methods też są czytelne i one nigdzie nie odchodzą. Jeśli będę pisał coś niskopoziomowego to na pewno z nich skorzystam. Hooki to inna warstwa abstrakcji — zamiast myśleć o cyklu życia komponentu, myślę tylko o cyklu życia mojego stanu: stworzenie, zmiana, odmontowanie.
[…] React Hooks — wprowadzenie i motywacja […]
[…] React Hooks — wprowadzenie i motywacja […]