Kategorie
Archiwum Newslettera

Jak zarzadzać stanem aplikacji React

React daje mi gotowe narzędzia do zarządzania stanem – hooki useState i useReducer. Mam też do dyspozycji React Context API. Natomiast nieprzemyślana struktura hooków i poplątanie zależności prowadzi do bugów i problemów z logicznym poukładaniem wszystkiego w dobrze zorganizowany organizm. Do tego dochodzi potrzeba optymalizowania wszystkiego na własną rękę.

React daje mi gotowe narzędzia do zarządzania stanem – hooki useState i useReducer. Mam też do dyspozycji React Context API. Natomiast nieprzemyślana struktura hooków i poplątanie zależności prowadzi do bugów i problemów z logicznym poukładaniem wszystkiego w dobrze zorganizowany organizm. Do tego dochodzi potrzeba optymalizowania wszystkiego na własną rękę.

Kiedy użyć biblioteki do zarządzania stanem użyć w ReactJS?

Staram się nie używać żadnej biblioteki do zarządzania stanem, dopóki nie jestem pewien, że przyniesie mi ona wymierne korzyści. Dopóki czegoś faktycznie nie poprawi. Może to być usprawnienie dla programisty, podniesienie wydajności lub bardziej wymierna potrzeba biznesowa. Zwracam też uwagę jak dana biblioteka wpłynie na przepływ danych w mojej aplikacji.

React ma swój sposób na przepływ danych. Biblioteki mogą mi ten przepływ zmienić, bardziej skomplikować. Sięgam po biblioteki do zarządzania stanem, gdy mam problem z samodzielnym jego ogrywaniem. Kiedy sam React zaczyna mnie ograniczać. Jeśli nie wiesz jak działa hook useState, to nie polecam zabierać się za żadną z poniższych bibliotek.

Co może poprawić biblioteka do zarządzania stanem?

Załóżmy, że już wiem, że powinienem się za czym rozglądać. Jakimi kryteriami się kieruję? Muszę zadać sobie odpowiednie pytanie. Na czym mi tak na prawdę zależy?

  • zapamiętywanie stanu, który ma istnieć po usunięciu komponentu z DOM
  • zaprojektowanie lepszych struktur i modeli danych
  • poprawienie wydajności
  • szybsze dostarczanie nowych funkcjonalności w przyszłości
  • kod bardziej odporny na błędy
  • podniesienie czytelności kodu
  • lepiej testowalny i bardziej przewidywalny kod
  • optymalizacja żądań HTTP

Raczej nie uda mi się zredukować ilości pisanego kodu. Wiem o tym, że pisząc więcej kodu, mogę kupić święty spokój. Na początek polecam potestować na osobnym branchu. Warto poszukać sekcji getting started w dokumentacji.

W czym może pomóc samo React Context API?

W większości przypadków mogę użyć React Context API, który rozwiązuje podstawowy problem Prop Drilling. Chodzi o to, aby nie przekazywać tych samych props wgłąb przez wiele komponentów. Przeciwieństwem jest wstrzykiwanie danych bezpośrednio do komponentu poprzez użycie hooka useContext. Pomocne przy tym będą również custom hooki. O optymalizację muszę wtedy zadbać samemu hookami useMemo i useCallback.

Co wybrać? Redux, Mobx czy jeszcze coś innego?

Redux

Stan jest niemutowalny, czyli taki jak w Reakcie, łatwiej migrować. Minusem jest duża ilość generowanego kodu boilerplate. Prawie zawsze chce użyć TypeScripta. I tutaj powstaje pytanie: jak typować stan i akcje? Jest wiele strategi typowania. Czy redux ma wysoki poziom wejścia? Na początek trzeba ogarnąć o co chodzi z tą niemutowalnością (immutability). Następnie zrozumieć co robią akcje i selectory. Mam do tego hook useDispatch i useSelector. Może to być trudne do przyswojenia dla nowicjuszy w samym Reakcie. Do doświadczonych programistów przemówi przewidywalność i łatwość w testowaniu. Powstała masa publikacji i opracowań różnych scenariuszy. Wisienką na torcie są Redux DevTools, które wspierają time-traveling 🚀

Mobx

Nie będę ukrywać, że nie mam dużego doświadczenia w Mobx. Zawsze denerwowało mnie to, że stan jest w nim mutowalny. Przez to tworzą się w aplikacji takie dwie strefy. W każdej obowiązują inne prawa. Z Mobx natomiast na pewno łatwiej zacząć. Mniej bilerplate i bardzo czytelny kod. Gratka dla miłośników klas i programowania obiektowego. Bardziej uwidoczniony model oberver i observable.

react-query

Warto też wspomnieć, że dane zewnętrzne mogą być wrzucane do cache’a już na etapie ich pobierania przez klienta HTTP. Może się wtedy okazać, ze globalny stan nie jest w ogóle potrzbny, bo całą robotę wykonuje właśnie ten cache. To robotę robi libka react-query. Ma bardzo przyjemne dev tools. Game changer w aplikacjach gdzie, głównym problemem jest optymalizacja żądań HTTP. Zdejmuje to ze mnie ciężar myślenia o tym, że nie mogę zbyt często wołać o dane z serwera, żeby nie obciążać łącza.

xstate

Maszyny stanowe to temat zaawansowany. W momencie pisania tego zdania, nawet nie mam w tym żadnego doświadczenia. Natomiast jestem przekonany, że w niedalekiej przyszłości tego użyję. Wybiorę xstate, gdy będę potrzebował bronić się przed wchodzeniem w niepoprawne stany. Dla przykładu: zakładam, że nie może wystąpić sytuacja, że ładujemy dane i jednocześnie jest ustawiony błąd. To tyle na dziś. Nie będę się wymądrzał, bo sam tego jeszcze nie umiem 😅