Jak používat Redux ve vysoce škálovatelných javascriptových aplikacích?

Redux složení a zapouzdření ve velkém měřítku

Vytváření rozsáhlé aplikace může být problematické, a jak roste, stává se stále náročnější a rozhodující pro zachování struktury. Redux poskytuje velké výhody z toho, že má globální stav aplikace, ale na druhé straně se může snadno zmatit a poškodit vaši aplikaci.

Dříve jsem demonstroval, jak lépe organizovat vaše aplikace React, kde vystavuji výhody architektury založené na funkcích pro aplikace React. Pokud potřebujete použít Redux, můžete se divit, jak můžete tuto strukturu použít a použít stejný typ oddělení obav bez bolesti.

Nedávno jsem pracoval pro první verzi mobilní aplikace React-Native pro jednoho z mých klientů, která si přála architekturu aplikace škálovatelným způsobem, aby byl bezbolestný zážitek a později přidávat nové funkce. Věřím, že bychom měli vždy přemýšlet o architektuře aplikací tak, jak se to může vždy později rozšířit, a myslím, že je skvělý nápad ukázat vám, jak jsem to zvládl na straně Redux věcí s několika příklady kódu. Nechte se inspirovat a přizpůsobte jej svým vlastním potřebám.

Proč je obtížné udržovat můj stav Redux, když moje aplikace roste?

Redux je velmi skvělý nástroj a možná budete chtít použít z mnoha důvodů. Možná budete muset sdílet nějaký stav z konkrétní součásti, aniž byste jej museli předávat prostřednictvím rekvizit, získávat data ze serverového rozhraní API a sdílet je v celé své aplikaci, udržovat historii a čas-cestovat po akcích nebo dokonce ukládat stav aplikace v místní úložiště zařízení uživatele a později je obnoví. Ale nikdy nezapomeňte, možná nebudete potřebovat redux.

Pokud se rozhodnete použít Redux, je důležité udržovat stavový strom dobře strukturovaný, aby mohl růst s růstem vaší aplikace.

Pokud máte problémy se stavem Redux, je pravděpodobné, že budete mít problémy se zachováním celé své aplikace ze stejných důvodů.

  • Máte příliš mnoho tvůrců globálních akcí?
  • Máte obrovský reduktor, který vše řídí?
  • Máte konflikty mezi vašimi činy nebo redukcemi, které mění stejný stav?

Ve většině případů je to důsledek ztráty kontroly a porozumění chování aplikace a vynakládáte více času na ladění než kódování. Pravdivý příběh.

Přidejte své soubory Redux s funkcí

Můžete určit, kdy má aplikace dobrou architekturu, když je rozdělena do několika malých funkcí, které lze snadno extrahovat a publikovat ve správci balíků a znovu použít jinou aplikací. Není nic horšího, než procházet starý adresář projektových složek a není schopen zjistit, zda jsou některé funkce nebo zdroje stále používány někde v aplikaci, protože někdo je zapomněl smazat, zatímco refaktoroval nějaký kód.

Proto byste chtěli definovat své tvůrce a redukce akcí Redux v rámci funkce, která je spotřebovává, aby sledovala, co se používá a kde se používá. Pokud se rozhodnete, že chcete odebrat celou funkci aplikace, můžete ji jednoduše odpojit a smazat celou složku, která obsahuje kontejner a prezentační komponenty, redukce, akce, zdroje atd., A víte, že to bude v pořádku, protože stav je není spojen s žádnou jinou funkcí. Rychlé, čisté a snadné.

S rostoucí aplikací se vaše funkce stávají složitějšími. Chcete-li se vyhnout jediné funkci, která spravuje příliš mnoho věcí, musíte je rozdělit do několika menších funkcí.

Funkce musí mít vše, co potřebuje pro vlastní práci. Musí mít také omezený rozsah a v ideálním případě žádné povědomí o celé aplikaci, ale někdy je to obtížné, protože součásti kontejneru si budou muset být vědomy tvaru stavu Redux. Samozřejmě můžete prvky vnořit do prvků tak dlouho, dokud zůstanou co nejvíce samostatně a vnořené prvky budou využívat pouze jejich přímí rodiče.

Knihy níže jsou scénou, jednou z funkcí aplikace. Má dílčí funkci ListItems, která je jednoduchou prezentační komponentou. Scéna má také vlastní akce a redukce definované ve složce objektu, kde tvůrci akcí používají komponenta kontejneru objektu.

/ scény
  / Knihy
    / komponenty
      / ListItems
    /actions.js
    /index.js
    /reducer.js

Stejným způsobem jako při sestavování svých funkcí do menších, měli byste toto pravidlo použít také na reduktory a rozdělit je, aby se daly snadno číst a udržovat. Při takovém složení je vhodnější ponechat strukturu celého stromu stavu Reduxu podle struktury složek vašich funkcí.

Vytvořte samostatné datové moduly

Komponenty kontejneru většinou spotřebovávají data, která nejsou pevně vázána na konkrétní komponentu, a můžete se divit, kde mají být definováni tvůrci a redukční prvky akcí. Způsob, jak to udělat, je vytvořit datové moduly, které se starají o jednotlivé datové objekty.

Odpovědnost jádra datového modulu spočívá ve správě kusů dat vašeho státu Redux. Jako příklad můžete mít modul, který spravuje objekt uživatelů, a jiný modul pro objekt knih. Datové moduly můžete vnořit do sebe tak dlouho, dokud zůstanou samostatné, stejným způsobem, jak jsou prvky sestavovány.

Anatomie datového modulu vypadá takto:

Tvůrci akcí

Postarají se o obchodní logickou část. Dostanou užitečnou zátěž, transformují ji podle potřeby a vracejí akci, která je odeslána k aktualizaci úložiště Redux. Ve většině projektů můžete také chtít použít redux-thunk, abyste měli asynchronní akce, jako je odesílání požadavků na serverové API.

Reduktory a selektory

Redukce zpracovávají akce a aktualizují stav Redux. Vaše reduktory by neměly mít žádnou logiku, protože musí zůstat čisté. Pokud máte tendenci mít logický kód, měli byste místo toho vytvořit jinou akci.

Selektory jsou důležité, pokud chcete svůj stav filtrovat dříve, než je použijete v komponentách kontejneru. Můžete je definovat v souboru reducer.js, protože jsou vázáni ke stejnému kusu státu.

API

Doporučuji vytvořit soubor s názvem api.js, kde můžete definovat vaše síťové požadavky.

Viděl jsem mnoho projektů, kde jediný způsob, jak odeslat požadavek API, byl přes middleware Redux, což naznačuje, že každé volání bude mít dopad na obchod Redux. To však není pravda, mohli byste mít volání API, která neovlivní obchod, například jednoduchý požadavek POST na odeslání e-mailu, záleží na tom, jak jste si uspořádali aplikaci. Z tohoto důvodu je však raději definuji v samostatném souboru.

Jakmile je datový modul definován, stačí importovat a kombinovat jeho reduktor s reduktorem dat, který se kombinuje spolu s hlavním reduktorem vaší funkce.

Sestavte více funkcí do jedné

Nyní, když jsou vaše funkce samostatné se svými vlastními akcemi a reduktory, musíte je sestavit pomocí koncepce reduktoru, kde je reduktor nazýván jiným reduktorem.

V níže uvedeném příkladu jsou 2 datové moduly. Modul uživatelských dat je definován globálně, což znamená, že jakákoli funkce z něj může importovat tvůrce akcí a použít jej k provedení změny v podskupině uživatelů. Modul údajů o knihách je však vnořen do scény Knihy, protože se používá pouze v rámci funkce Knihy. Aby všechno fungovalo, musíte sestavit hlavní reduktor každého prvku dítěte do redukce rodičovského prvku. Můžete to udělat s kombinovanými reduktory nebo ručně, pokud máte komplexní datovou strukturu.

Pro každou datovou složku máme reduktor zodpovědný za kombinování všech datových modulů definovaných v této složce. I když reduktor může vrátit pouze jeden datový modul, v příštím přidání dalších datových modulů, které budou přidány v budoucnu, a aby vše zůstalo konzistentní v celé aplikaci, je lepší nechat je všechny importovat a kombinovat v jednom reduktoru, takže redukce vaší funkce můžete jednoduše importovat a použít k zpřístupnění všech datových modulů najednou. Omezovač funkce se poté použije reduktorem přímého nadřazeného prvku nebo reduktorem kořenů, pokud je definován na globální úrovni.

Takto vypadá reduktor ve scénách / knihách zapouzdřujících datové moduly:

V tomto příkladu reduktor zachycuje akce z datového modulu, aby nastavil stav načítání, kdykoli je požadavek na načtení nových dat. Stejnou akci můžete zvládnout v několika reduktorech nebo naopak a mutovat to, co je relevantní. To vám pomůže rozšířit vývoj aplikací, protože různí lidé ve vašem týmu mohou pracovat na různých funkcích a datových modulech, které zpracovávají stejné akce, aniž by při vzájemném narážení do druhého kódu způsobovaly konflikty slučování.

Jakmile správně zkombinujete reduktory pro všechny své funkce, měl by strom stavu aplikace Redux vypadat takto:

Nyní, když jsou vaše redukce sestaveny podle této struktury, mohou se komponenty vašeho kontejneru připojit k úložišti Redux a pomocí vybraných selektorů, které jste dříve definovali, spotřebovat data a odesílat akce vaší funkce, aby v obchodě provedli změny.

Zabalení

Doufám, že se už nebojíte, pokud jde o vytváření vysoce škálovatelných webových nebo mobilních aplikací javascript s Redux. Bez ohledu na to, jak velká bude vaše aplikace, bude po takovéto struktuře udržet bezpečí před neočekávanými událostmi a rostoucími problémy.

Na svém účtu Github jsem zveřejnil ukázkový projekt, který sleduje tuto strukturu: https://github.com/alexmngn/react-feedback-form

Neváhejte a přidejte odpověď níže nebo mě přímo kontaktujte, pokud máte nějaké dotazy, rádi vám pomůžeme.

Další články ode mě

  • Jak lépe organizovat své aplikace React?
  • Jaké jsou hlavní rozdíly mezi ReactJS a React-Native?
  • Nezbytná základní deska pro ověření uživatelů ve vaší aplikaci React-Native

O mně

Ahoj, já jsem Alexis! Jsem vývojář aplikací Javascript, který programuje více než 15 let. Specializuji se na architekturu a vývoj vysoce škálovatelných webových a mobilních aplikací při funkčním programování. Nedávno jsem začal používat Twitter, můžete mě sledovat zde: @alexmngn