Context API w React
Każda kolejna wersja Reacta dostarcza nam coraz lepszych i ciekawszych narzędzi, które mają poprawić jakość naszej pracy z kodem, który tworzymy. Nie inaczej jest z Context API, które pojawiło się w React w wersji 16.3.
Z tego artykułu dowiesz się:
Co to jest Context API
W jakim celu powstało i jakie problemy ma rozwiązywać
Jak używać Context API poprzez propsy oraz z wykorzystaniem hook'a useContext
Jak Context API może nam pomóc?
W klasycznej aplikacji napisanej w React dane są przekazywane z góry w dół pomiędzy komponentami za pomocą propsów. Zdarzają się sytuacje, gdy komponent zagnieżdżony kilka poziomów niżej potrzebuje danych z najwyższego komponentu. Prowadzi to do sytuacji, kiedy musimy przekazać propsy w dół przez kilka komponentów.
W powyższym przykładzie widzimy, że informacje o zalogowanym użytkowniku potrzebne są w komponentach <UserAvatar />
oraz <UserName />
, natomiast samo logowanie odbywa się w komponencie najwyższego poziomu <App />
. Aby dane o zalogowanym użytkowniku stały się dostępne dla komponentów położych najniżej w drzewie Virtual DOM musimy przekazać je za pomocą propsów. Ta technika nazywa się props drilling.
Teoretycznie moglibyśmy trzymać informacje o naszym użytkowniku w obiekcie globalnym, ale co do zasady przechowywanie danych w obiektach globalnych nie jest najlepszym rozwiązaniem. Mielibyśmy zdecydowanie mniejszą kontrolę nad tym co się dzieje z naszym obiektem, gdzie i w jakich miejscach jest modyfikowany.
Alternatywnie dla przekazywania danych poprzez props drilling można skorzystać z takich narzędzi jak Redux czy MobX. Musimy sobie jednak odpowiedzieć na pytanie czy opłaca nam się podpinać do naszego projektu kolejną bibliotekę - pamiętajmy, że zwiększymy ilość kodu, dołożymy sporo dodatkowej abstrakcji i zwiększymy koszty utrzymania naszej aplikacji.
React Context API to kolejna z opcji rozwiązania powyższego problemu.
Context API w praktyce
Context API zdecydowanie ułatwia pracę w sytuacjach, gdy komponenty niższego poziomu muszą dowiedzieć się o zmianach czy też muszą mieć dostęp do określonych danych. Zbudowanie konktekstu to wywołanie jednej funkcji, udostępnionej w API Reacta.
Context, Provider, Consumer
Tworzenie kontekstu to tak naprawdę wywołania jednej funkcji, która przyjmuje wartość domyślną. Wartość domyślna przyda nam się w dwóch przypadkach:
gdy Consumer nie znajdzie Providera
gdy Provider nie będzie miał przypisanego props’a value
Wyżej wspomniałem o dwóch nowych komponentach: Consumer oraz Provider. Funkcja createContext
zwraca nam dwa nowe komponenty. Jeden z nich odpowiedzialny jest za dostarczanie kontekstu swoim dzieciom (<Provider />
), drugi natomiast służy do odczytania aktualnej wartości kontekstu (<Consumer />
).
Provider wymaga podania jednego propsa value
. value
to wartość domyślna, która zostanie przekazana do Consumera
jako pierwsza. Jak widać w kodzie poniżej w stanie komponentu App
trzymamy zmienną user
, która jest aktualizowana po kliknięciu w button. Każda zmiana stanu komponentu App
wyemituje informacje do Consumer'ów
o tej zmianie.
Zwróć uwagę, że zarówno komponent Hi
, jak i Header
nie przyjmują w propsach user
.
Render props
W powyższym przykładzie mamy jeden z kilku sposobów wyciągnięcia danych w komponencie Consumer
. Dzieckiem naszego Consumer'a
jest funkcja. Nasza funkcja przyjmuje jeden parametr, który jest dokładnie tą samą wartością, która została przekazana do value
naszego Provider'a
. Taka implementacja, gdy funkcja jest dzieckiem komponentu nazywa się render props
. Technika ta wykorzystywana jest do udostępniania kodu pomiędzy różnymi komponentami. Więcej na ten temat znajdziesz w dokumentacji.
useContext
Innym sposobem na wyciągnięcie danych z Consumer'a
jest wykorzystanie Hook’a useContext
, który jest dostarczany razem z Reactem. Wykorzystanie useContext
ograniczy nam skomplikowanie naszego kodu. Poniżej przykład:
useContext
przyjmuje jako argument nasz kontekst i zwraca zasubskrybowaną wartość zwracaną przez Provider
.
Wykorzystanie w praktyce
Czy warto zawsze i wszędzie wykorzystywać Context Api? Odpowiedź na to pytanie jest bardzo trudna, ponieważ zależy od wielu czynników. Czasami props drilling
jest konieczne, czasami wykorzystanie takich bibliotek jak Redux czy MobX może być bardziej zasadne niż skorzystanie z nowości, jaką jest Context API.
Bardzo często podaje się 3 najpopularniejsze przykłady, gdy warto wykorzystać Context API.
Themes
Poprawienie User Experience to zawsze dobry pomysł. Z Context API o wiele łatwiej wdrożyć zarządzanie theme’ami w naszym projekcie. Przełączenie się pomiędzy dark mode a light mode z Context API może być bardzo proste. Nasz kontekst może trzymać odpowiednie ustawienia w obiekcie. Z Context API przełączenie theme’u nie będzie wymagało przekazywania kolejnych propsów, które niewątpliwie zmniejszą czytelność naszego kodu.
Wielojęzyczność
Podobnie jak przypadku zmieniania theme’u, zmiana wersji języka z Context API również będzie bardzo dobrym pomysłem.
Autoryzacja
Nie bez powodów wybrałem autoryzację jako prosty przykład w moim poście. Jest to chyba najbardziej oczywisty przykład tego jak Context API może nam pomóc. Przekazywanie danych użytkownika przez całe drzewo komponentów nie brzmi jak dobry pomysł, tym bardziej, że tak naprawdę większość komponentów nie będzie tych danych potrzebowała.
Podsumowanie
Context API to kolejne bardzo dobre narzędzie dołączone do React’a. Wydaje mi się, że może być bardzo przydatne i może pomóc w rozwiązaniu bardzo wielu przypadków, które jak dotąd mogły spędzać nam sen z powiek. Warto zwrócić uwagę na fakt, że Context API nie może zastąpić Redux’a czy MobXa - ponieważ każde z tych narzędzi może być użyteczne w inny sposób. Pamietajmy też, że do zarządzania stanem naszej aplikacji nie zawsze musimy zaprzęgać dodatkową bibliotekę.
Komentarze (0)
Jeszcze nikt nic nie napisał, ale to znaczy że... możesz być pierwszy/pierwsza.