Redux · Wprowadzenie

Opublikowany: 2022-03-10
Szybkie podsumowanie ↬ Redux jest obecnie jedną z najgorętszych bibliotek w rozwoju front-end. Jednak wiele osób jest zdezorientowanych, co to jest i jakie są jego zalety. Jak podano w dokumentacji, Redux to przewidywalny kontener stanu dla aplikacji JavaScript . Mówiąc inaczej, jest to architektura przepływu danych aplikacji, a nie tradycyjna biblioteka lub framework, taki jak Underscore.js i AngularJS.

Redux jest obecnie jedną z najgorętszych bibliotek w rozwoju front-end. Jednak wiele osób jest zdezorientowanych, co to jest i jakie są jego zalety.

Jak stwierdza dokumentacja, Redux jest przewidywalnym kontenerem stanu dla aplikacji JavaScript. Mówiąc inaczej, jest to architektura przepływu danych aplikacji, a nie tradycyjna biblioteka lub framework, taki jak Underscore.js i AngularJS.

Dalsze czytanie na SmashingMag

  • Dlaczego powinieneś rozważyć React Native dla swojej aplikacji mobilnej
  • Automatyzacja testów aplikacji, gier i sieci mobilnej
  • Renderowanie po stronie serwera za pomocą React, Node i Express
  • Uwagi dotyczące dostępności renderowanej przez klienta

Redux został stworzony przez Dana Abramova około czerwca 2015 roku. Zainspirował go Flux Facebooka i funkcjonalny język programowania Elm. Redux stał się popularny bardzo szybko dzięki swojej prostocie , małym rozmiarom (tylko 2 KB) i świetnej dokumentacji. Jeśli chcesz dowiedzieć się, jak Redux działa wewnętrznie i zagłębić się w bibliotekę, rozważ skorzystanie z bezpłatnego kursu Dana.

Więcej po skoku! Kontynuuj czytanie poniżej ↓

Redux jest używany głównie do zarządzania stanem aplikacji. Podsumowując, Redux utrzymuje stan całej aplikacji w jednym niezmiennym drzewie stanów (obiektu), którego nie można zmienić bezpośrednio. Gdy coś się zmienia, tworzony jest nowy obiekt (za pomocą akcji i reduktorów). Poniżej szczegółowo omówimy podstawowe koncepcje.

Czym różni się od MVC i Flux?

Aby dać pewną perspektywę, weźmy klasyczny wzorzec model-widok-kontroler (MVC), ponieważ większość programistów jest z nim zaznajomiona. W architekturze MVC istnieje wyraźne rozdzielenie danych (model), prezentacji (widok) i logiki (kontroler). Jest z tym jeden problem, szczególnie w aplikacjach na dużą skalę: przepływ danych jest dwukierunkowy. Oznacza to, że jedna zmiana (dane wejściowe użytkownika lub odpowiedź API) może wpłynąć na stan aplikacji w wielu miejscach w kodzie — na przykład dwukierunkowe wiązanie danych. To może być trudne do utrzymania i debugowania.

Flux jest bardzo podobny do Redux. Główną różnicą jest to, że Flux ma wiele magazynów, które zmieniają stan aplikacji i rozgłasza te zmiany jako zdarzenia. Komponenty mogą subskrybować te zdarzenia w celu synchronizacji z bieżącym stanem. Redux nie ma dyspozytora , który w Flux jest używany do rozgłaszania ładunków do zarejestrowanych wywołań zwrotnych. Kolejną różnicą w Flux jest to, że dostępnych jest wiele odmian, co powoduje pewne zamieszanie i niespójność.

Korzyści z Redux

Możesz zapytać: „Dlaczego miałbym używać Redux?” Świetne pytanie. Istnieje kilka korzyści z używania Redux w następnej aplikacji:

  • Przewidywalność wyniku
    Zawsze istnieje jedno źródło prawdy, sklep, bez żadnych wątpliwości co do tego, jak zsynchronizować bieżący stan z działaniami i innymi częściami aplikacji.
  • Utrzymywalność
    Posiadanie przewidywalnego wyniku i ścisłej struktury ułatwia utrzymanie kodu.
  • Organizacja
    Redux bardziej rygorystycznie określa sposób organizacji kodu, co sprawia, że ​​kod jest bardziej spójny i łatwiejszy dla zespołu.
  • Renderowanie serwera
    Jest to bardzo przydatne, szczególnie w przypadku wstępnego renderowania, co zapewnia lepsze wrażenia użytkownika lub optymalizację pod kątem wyszukiwarek. Wystarczy przekazać sklep utworzony na serwerze po stronie klienta.
  • Narzędzia deweloperskie
    Deweloperzy mogą śledzić wszystko, co dzieje się w aplikacji w czasie rzeczywistym, od działań po zmiany stanu.
  • Społeczność i ekosystem
    To ogromny plus, gdy uczysz się lub korzystasz z dowolnej biblioteki lub frameworka. Posiadanie społeczności stojącej za Redux czyni go jeszcze bardziej atrakcyjnym w użyciu.
  • Łatwość testowania
    Pierwszą zasadą pisania testowalnego kodu jest pisanie małych funkcji, które wykonują tylko jedną rzecz i są niezależne. Kod Redux to głównie funkcje, które są właśnie takie: małe, czyste i izolowane.

Programowanie funkcjonalne

Jak wspomniano, Redux został zbudowany na bazie koncepcji programowania funkcjonalnego. Zrozumienie tych pojęć jest bardzo ważne dla zrozumienia, jak i dlaczego Redux działa tak, jak działa. Przyjrzyjmy się podstawowym pojęciom programowania funkcjonalnego:

  • Potrafi traktować funkcje jako obiekty pierwszej klasy.
  • Jest w stanie przekazywać funkcje jako argumenty.
  • Jest w stanie kontrolować przepływ za pomocą funkcji, rekurencji i tablic.
  • Jest w stanie używać funkcji czystych, rekurencyjnych, wyższego rzędu, zamykania i anonimowych.
  • Jest w stanie korzystać z funkcji pomocniczych, takich jak mapowanie, filtrowanie i zmniejszanie.
  • Jest w stanie łączyć ze sobą funkcje.
  • Stan się nie zmienia (tzn. jest niezmienny).
  • Kolejność wykonywania kodu nie jest istotna.

Programowanie funkcjonalne pozwala nam pisać czystszy i bardziej modułowy kod. Pisząc mniejsze i prostsze funkcje, które są izolowane pod względem zakresu i logiki, możemy znacznie ułatwić testowanie, konserwację i debugowanie kodu. Teraz te mniejsze funkcje stają się kodem wielokrotnego użytku , a to pozwala pisać mniej kodu, a mniej kodu jest dobrą rzeczą. Funkcje można kopiować i wklejać w dowolnym miejscu bez żadnych modyfikacji. Funkcje, które są izolowane w zakresie i wykonują tylko jedno zadanie, będą w mniejszym stopniu zależeć od innych modułów w aplikacji, a to zmniejszone sprzężenie jest kolejną zaletą programowania funkcjonalnego.

01-funkcjonalne-programowanie-opt-podgląd
Przykład programowania funkcjonalnego (Zdjęcie: Tanya Bachuk) (Zobacz w powiększonej wersji)

Podczas pracy z funkcjonalnym JavaScriptem zobaczysz między innymi czyste funkcje, funkcje anonimowe, domknięcia, funkcje wyższego rzędu i łańcuchy metod. Redux intensywnie używa czystych funkcji, dlatego ważne jest, aby zrozumieć, czym one są.

Czyste funkcje zwracają nową wartość na podstawie przekazanych im argumentów. Nie modyfikują istniejących obiektów; zamiast tego zwracają nowy. Funkcje te nie polegają na stanie, z którego są wywoływane, i zwracają tylko jeden i ten sam wynik dla dowolnego podanego argumentu. Z tego powodu są bardzo przewidywalne.

Ponieważ funkcje pure nie modyfikują żadnych wartości, nie mają żadnego wpływu na zakres ani żadne obserwowalne efekty uboczne, a to oznacza, że ​​programista może skupić się tylko na wartościach zwracanych przez funkcję pure.

Gdzie można zastosować Redux?

Większość programistów kojarzy Redux z Reactem, ale można go używać z dowolną inną biblioteką widoków. Na przykład możesz użyć Redux z AngularJS, Vue.js, Polymer, Ember, Backbone.js i Meteor. Jednak Redux plus React to wciąż najpopularniejsza kombinacja. Upewnij się, że uczysz się React we właściwej kolejności: Najlepszym przewodnikiem jest Pete Hunt, który jest bardzo pomocny dla programistów, którzy zaczynają przygodę z Reactem i są przytłoczeni wszystkim, co dzieje się w ekosystemie. Zmęczenie JavaScript jest uzasadnionym problemem wśród programistów front-end, zarówno nowych, jak i doświadczonych, więc poświęć trochę czasu na nauczenie się React lub Redux we właściwy sposób we właściwej kolejności.

Jednym z powodów, dla których Redux jest niesamowity, jest jego ekosystem. Dostępnych jest tak wiele artykułów, samouczków, oprogramowania pośredniczącego, narzędzi i szablonów. Osobiście korzystam z boilerplate’u Davida Żukowskiego, ponieważ ma wszystko, czego potrzeba do zbudowania aplikacji JavaScript, z React, Redux i React Router. Słowo ostrzeżenia: staraj się nie używać szablonów i zestawów startowych podczas nauki nowych frameworków, takich jak React i Redux. Sprawi to, że będzie jeszcze bardziej zagmatwany, ponieważ nie zrozumiesz, jak wszystko działa razem. Naucz się go najpierw i stwórz bardzo prostą aplikację, najlepiej jako projekt poboczny, a następnie użyj szablonów dla aplikacji produkcyjnych, aby zaoszczędzić czas.

Budowanie części Redux

Koncepcje Redux mogą wydawać się skomplikowane lub fantazyjne, ale są proste. Pamiętaj, że biblioteka ma tylko 2 KB. Redux ma trzy części budowlane: akcje, sklep i redukcje.

02-reux-data-flow-opt-preview
Przepływ danych Redux (Zdjęcie: Tanya Bachuk) (Zobacz w dużej wersji)

Porozmawiajmy o tym, co każdy z nich robi.

działania

Krótko mówiąc, działania to zdarzenia. Akcje wysyłają dane z aplikacji (interakcje użytkowników, zdarzenia wewnętrzne, takie jak wywołania API i przesyłanie formularzy) do sklepu. Sklep uzyskuje informacje tylko z akcji. Akcje wewnętrzne to proste obiekty JavaScript, które posiadają właściwość type (zazwyczaj stałą), opisującą typ akcji i ładunek informacji przesyłanych do sklepu.

 { type: LOGIN_FORM_SUBMIT, payload: {username: 'alex', password: '123456'} }

Akcje są tworzone za pomocą twórców akcji. Wiem, brzmi to oczywiste. To tylko funkcje, które zwracają akcje.

 function authUser(form) { return { type: LOGIN_FORM_SUBMIT, payload: form } }

Wywoływanie akcji w dowolnym miejscu aplikacji jest zatem bardzo łatwe. Użyj metody dispatch , na przykład:

 dispatch(authUser(form));

Reduktory

Omówiliśmy już, czym jest reduktor w funkcjonalnym JavaScript. Opiera się na metodzie array reduction, która akceptuje wywołanie zwrotne (reduktor) i pozwala uzyskać pojedynczą wartość z wielu wartości, sum liczb całkowitych lub akumulacji strumieni wartości. W Redux reduktory to funkcje (czyste), które pobierają aktualny stan aplikacji i akcji, a następnie zwracają nowy stan. Zrozumienie, jak działają reduktory, jest ważne, ponieważ wykonują większość pracy. Oto bardzo prosty reduktor, który przyjmuje bieżący stan i akcję jako argumenty, a następnie zwraca następny stan:

 function handleAuth(state, action) { return _.assign({}, state, { auth: action.payload }); }

W przypadku bardziej złożonych aplikacji możliwe jest użycie narzędzia combineReducers() dostarczanego przez Redux (w rzeczywistości zalecane). Łączy wszystkie reduktory w aplikacji w jeden reduktor indeksu. Każdy reduktor odpowiada za swoją część stanu aplikacji, a parametr state jest inny dla każdego reduktora. Narzędzie combineReducers() znacznie ułatwia utrzymanie struktury plików.

Jeśli obiekt (stan) zmienia tylko niektóre wartości, Redux tworzy nowy obiekt, wartości, które nie uległy zmianie, będą odnosić się do starego obiektu i zostaną utworzone tylko nowe wartości. To świetnie nadaje się do wydajności. Aby uczynić go jeszcze bardziej wydajnym, możesz dodać Immutable.js.

 const rootReducer = combineReducers({ handleAuth: handleAuth, editProfile: editProfile, changePassword: changePassword });

Sklep

Store to obiekt, który przechowuje stan aplikacji i udostępnia kilka metod pomocniczych w celu uzyskania dostępu do stanu, akcji wysyłania i rejestrowania detektorów. Cały stan jest reprezentowany przez jeden sklep. Każda akcja zwraca nowy stan za pośrednictwem reduktorów. To sprawia, że ​​Redux jest bardzo prosty i przewidywalny.

 import { createStore } from 'redux'; let store = createStore(rootReducer); let authInfo = {username: 'alex', password: '123456'}; store.dispatch(authUser(authInfo));

Narzędzia programistyczne, podróże w czasie i ponowne ładowanie na gorąco

Aby ułatwić pracę z Redux, zwłaszcza podczas pracy z aplikacją o dużej skali, polecam korzystanie z Redux DevTools. Jest niezwykle pomocny, pokazując zmiany stanu w czasie, zmiany w czasie rzeczywistym, działania i aktualny stan. Oszczędza to czas i wysiłek, unikając bieżącego stanu i działań console.log

03-redux-dev-tools-opt-podgląd
Redux DevTools (Zobacz w dużej wersji)

Redux ma nieco inną implementację podróży w czasie niż Flux. W Redux możesz cofnąć się do poprzedniego stanu, a nawet zmienić swój stan od tego momentu. Redux DevTools obsługuje następujące funkcje „podróży w czasie” w przepływie pracy Redux (pomyśl o nich jako o poleceniach Git dla twojego stanu):

  • Reset : resetuje do stanu, w którym został utworzony Twój sklep
  • Przywróć : wraca do ostatniego zatwierdzonego stanu
  • Sweep : usuwa wszystkie wyłączone akcje, które mogłeś uruchomić przez pomyłkę
  • Commit : sprawia, że ​​bieżący stan jest stanem początkowym

Funkcja podróży w czasie nie jest wydajna w środowisku produkcyjnym i jest przeznaczona tylko do programowania i debugowania. To samo dotyczy DevTools.

Redux znacznie ułatwia testowanie, ponieważ wykorzystuje funkcjonalny JavaScript jako podstawę, a małe niezależne funkcje są łatwe do przetestowania. Tak więc, jeśli potrzebujesz zmienić coś w swoim drzewie stanów, zaimportuj tylko jeden reduktor, który jest odpowiedzialny za ten stan i przetestuj go w izolacji.

Zbuduj aplikację

Na zakończenie tego wprowadzającego przewodnika zbudujmy bardzo prostą aplikację przy użyciu Redux i React. Aby ułatwić wszystkim śledzenie, będę trzymać się zwykłego starego JavaScriptu, używając ECMAScript 2015 i 2016 tak mało, jak to możliwe. Będziemy kontynuować logikę logowania rozpoczętą wcześniej w tym poście. Ten przykład nie używa żadnych danych na żywo, ponieważ celem tej aplikacji jest pokazanie, jak Redux zarządza stanem bardzo prostej aplikacji. Użyjemy CodePen.

1. Komponent reakcji

Potrzebujemy niektórych komponentów i danych React. Zróbmy prosty komponent i wyrenderujmy go na stronie. Komponent będzie miał pole wejściowe i przycisk (to bardzo prosty formularz logowania). Poniżej dodamy tekst, który reprezentuje nasz stan:

Zobacz Pen Intro to Redux autorstwa Alexa Bachuka (@abachuk) na CodePen.

Zobacz Pen Intro to Redux autorstwa Alexa Bachuka (@abachuk) na CodePen.

2. Wydarzenia i akcje

Dodajmy Redux do projektu i obsłużmy zdarzenie onClick dla przycisku. Jak tylko użytkownik się zaloguje, wyślemy akcję z typem LOGIN i wartością bieżącego użytkownika. Zanim to zrobimy, musimy stworzyć sklep i przekazać do niego funkcję redukującą jako argument. Na razie reduktor będzie tylko pustą funkcją:

Zobacz Pen Intro to Redux - Krok 2. Wydarzenia i działania Alexa Bachuka (@abachuk) w CodePen.

Zobacz Pen Intro to Redux - Krok 2. Wydarzenia i działania Alexa Bachuka (@abachuk) w CodePen.

3. Reduktory

Teraz, gdy mamy akcję odpalenia, reduktor podejmie tę akcję i przywróci nowy stan. Zajmijmy się akcją LOGIN zwracającą status zalogowania, a także dodajmy akcję LOGOUT , abyśmy mogli później z niej skorzystać. Reduktor auth przyjmuje dwa parametry:

  1. aktualny stan (który ma wartość domyślną),
  2. akcja.

Zobacz Pen Intro to Redux - Krok 3. Reduktory autorstwa Alexa Bachuka (@abachuk) na CodePen.

Zobacz Pen Intro to Redux - Krok 3. Reduktory autorstwa Alexa Bachuka (@abachuk) na CodePen.

4. Wyświetlanie aktualnego stanu

Teraz, gdy mamy już stan początkowy (wartość domyślna w reduktorze) i gotowy komponent React, zobaczmy, jak ten stan wygląda. Najlepszą praktyką jest zepchnięcie stanu do komponentów potomnych. Ponieważ mamy tylko jeden składnik, przekażmy stan aplikacji jako właściwość do składników auth . Aby wszystko działało razem, musimy zarejestrować detektor sklepu za pomocą metody pomocniczej subscribe , opakowując ReactDOM.render w funkcję i przekazując go do store.subscribe() :

Zobacz Pen Intro to Redux - Krok 4. Wyświetlanie aktualnego stanu przez Alex Bachuk (@abachuk) w CodePen.

Zobacz Pen Intro to Redux - Krok 4. Wyświetlanie aktualnego stanu przez Alex Bachuk (@abachuk) w CodePen.

5. Zaloguj się i wyloguj

Teraz, gdy mamy procedury obsługi akcji logowania i wylogowania, dodajmy przycisk wylogowania i wywołaj akcję LOGOUT . Ostatnim krokiem jest określenie, który przycisk ma wyświetlać logowanie lub wylogowanie poprzez przeniesienie tego logowania poza metodę render i renderowanie zmiennej poniżej:

Zobacz Pen Intro to Redux - Krok 5. Logowanie/Wylogowanie autorstwa Alex Bachuk (@abachuk) na CodePen.

Zobacz Pen Intro to Redux - Krok 5. Logowanie/Wylogowanie autorstwa Alex Bachuk (@abachuk) na CodePen.

Wniosek

Redux zyskuje na sile każdego dnia. Jest używany przez wiele firm (Uber, Khan Academy, Twitter) oraz w wielu projektach (Apollo, WordPress' Calypso), z powodzeniem w produkcji. Niektórzy programiści mogą narzekać, że jest to duże obciążenie. W większości przypadków do wykonania prostych czynności, takich jak klikanie przycisków lub proste zmiany interfejsu użytkownika, potrzeba więcej kodu. Redux nie pasuje do wszystkiego. Musi być równowaga. Być może proste czynności i zmiany interfejsu użytkownika nie muszą być częścią sklepu Redux i można je utrzymywać na poziomie komponentów.

Mimo że Redux może nie być idealnym rozwiązaniem dla Twojej aplikacji lub frameworka, gorąco polecam sprawdzenie go, szczególnie w przypadku aplikacji React.

Prawa autorskie do zdjęć na pierwszej stronie: Lynn Fisher, @lynnandtonic