Captain Hook. Redux Store z wykorzystaniem React Hooks

Wraz z nadejściem ery Web 2.0 strony internetowe przestały być jedynie prostymi dokumentami tekstowymi, a zaczęły być aplikacjami raczej przypominającymi aplikacje desktopowe. Użytkownicy dostali możliwość tworzenia i dostosowywania treści do własnych potrzeb. Z konsumentów Internetu przeobrazili się w jego twórców. Wiązało się to wieloma wyzwaniami, które stanęły przed programistami w związku z nowymi, prężnie rozwijającymi się technologiami. Chcąc dostarczyć użytkownikom jak najwięcej możliwości aplikacje klienckie zaczęły się rozrastać, a poziom ich skomplikowania spowodował, że także frontendowcy musieli zacząć myśleć o przechowywaniu i przepływie danych po stronie klientów. Co jednak zrobić, kiedy danych jest naprawdę dużo i stają się trudne do utrzymywania a ich przepływ niemożliwy do prześledzenia?

Tomasz Podkowski. Frontend Developer w firmie Merixstudio, gdzie chętnie podejmuje się projektów związanych z realizacją złożonych zadań wymagających kreatywnego podejścia do kodowania. Na co dzień podnosi swoje umiejętności programowania w Angularze, ale zgłębia również tajniki Reacta. Po godzinach relaksuje się przesłuchując swoją obszerną kolekcję płyt CD. 


Z propozycją rozwiązania tego problemu wyszedł sam Facebook, prezentując architekturę Flux, która sama w sobie jest raczej wzorcem pisania kodu, niż pełnoprawnym frameworkiem. Dzięki zastosowaniu jednokierunkowego przepływu danych, pozwala na jego dokładne prześledzenie i przeanalizowanie, a co za tym idzie zdecydowanie ułatwia pracę z kodem i jego późniejsze utrzymanie.

Jej pełnoprawnym zastosowaniem, dostarczającym API, które zostało oficjalnie wsparte przez twórcę Fluxa jest Redux. Niewielki framework (~2kB włączając w to zależności). Choć najczęściej kojarzony z Reactem, brak jest jakichkolwiek przeciwwskazań do wykorzystania go w parze z jakąkolwiek inną biblioteką do tworzenia UI.

Redux

Redux przechowuje stan całej aplikacji w strukturze drzewa obiektów w tzw. store. Dzięki pojedynczemu storowi, naszemu Single Source of Truth całej aplikacji, jesteśmy w stanie łatwo debugować i podglądać cały przepływ danych. Wszelkie zmiany wykonywane są jedynie za pomocą pure functions gdyż w celu zablokowania mutacji stora przez side-effecty ten jest skonfigurowany tak, aby był “tylko do odczytu”.

Akcje, Typy i Payload

Akcja to zwykły obiekt, którego zadaniem jest opisanie co stało się w aplikacji. To przez dispatch akcji informujemy o zmianie stanu aplikacji. Każda akcja powinna być opisana przez typ – string opisujący do czego dana akcja służy.

Reducers

Żeby powiązać stan z akcjami tworzymy reducery. To nic innego jak funkcje reagujące na każdą dispatchowaną akcję. Przyjmują dwa argumenty: state oraz akcję. Nie modyfikują one bezpośrednio stanu, a jedynie zwracają jego zaktualizowaną kopię.

Choć cała idea Reduxa wykorzystuje jedynie zwykły JavaScript, to jego integracja z daną biblioteką lub frameworkiem wymagać będzie wykorzystania konkretnego Redux API np. ng-redux czy react-redux. Czy możemy tego jakoś uniknąć? W Reactie tak.

Redux bez Reduxa?

React Hooks

Zaprezentowane w React 16.8. hooki w końcu pozwoliły użytkownikom tworzyć functional components bez obaw i problemów o zarządzaniem ich stanem. W końcu, aby móc korzystać ze state i lifecycle methods nie musimy już tworzyć class z ECMAScript 6. Hook to prosta funkcja, której parametrem jest wartość początkowa, a która zwraca listę dwóch elementów: pierwszym jest wartość, a drugim funkcja pozwalająca na zmianę tej wartości. Mała rzecz dająca spore możliwości.

Redux + React Hooks?

Jak zatem wykorzystać hooki do stworzenia Redux API? Tym razem odwróćmy kolejność i zacznijmy od reducera.

Powyższy reducer jest niemalże identyczny, jak ten nieprzeznaczony do współpracy z hookami. Jedyną różnicą pomiędzy nimi jest format w jakim zwracają dane. W pierwszym przypadku jest to po prostu state, natomiast w tym lista z dwoma elementami. Stwórzmy coś na kształt Redux API.

Funkcja userReducer to nic innego jak custom hook, dzięki któremu uzyskujemy dostęp do statu oraz funkcji umożliwiającej jego zmianę. Oczywiście zanim to nastąpi dane kierowane są do reducera.

Twórcy Reacta przewidzieli, że zarządzanie data-flow naszej aplikacji przy wykorzystaniu reducerów jest na tyle częstym przypadkiem, że sami dostarczyli nam custom hook o nazwie useReducer.

To w nim zawarli całą przedstawioną wcześniej logikę, dzięki czemu nie ma potrzeby pisania jej w całości od zera.

Zyski i straty

Dzięki wykorzystaniu React Hooks możemy stworzyć własną implementację Reduxa w naszej aplikacji. Nie musimy dzięki temu go pobierać i dodawać do projektu dodatkowych zależności, ale czy takie narzędzie będzie zawsze najlepszym wyborem? Odpowiem – pewnie nie. Redukujemy bundle o kilka kilobajtów, ale tracimy wszelką integrację choćby z takim narzędziem jak Redux DevTools. Wszystko więc jak zawsze zależy od projektu i wyobraźni programisty. Wybór technologii pozostawiam więc Wam.


Źródła:

Zdjęcie główne artykułu pochodzi z unsplash.com.

Zapraszamy do dyskusji

Patronujemy

 
 
Polecamy
Ofertę pracy znalazłem w opisie filmu na YT. Krzysztof Woliński o pracy w Japonii