Как да използвате Redux за силно мащабируеми приложения на JavaScript?

Redux състав и капсулиране в голям мащаб

Изграждането на широкомащабно приложение може да бъде проблематично и с нарастването му става все по-предизвикателно и решаващо да се поддържа структурата организирана. Redux предоставя големи ползи от наличието на глобално състояние на приложение, но от друга страна, той може да се обърка лесно и да счупи приложението ви.

По-рано демонстрирах Как по-добре да организирате вашите приложения React, където излагам предимствата на базирана на функции архитектура за React приложения. Ако се налага да използвате Redux, може да се чудите как можете да използвате тази структура и да приложите един и същ тип разделяне на проблемите без болката.

Наскоро съм работил върху първата версия на мобилно приложение React-Native за един от моите клиенти, което желае да архитектура приложението по мащабируем начин, за да безболезнено изживяване да добави нови функции по-късно. Вярвам, че винаги трябва да мислим за архитектурата на приложенията по този начин, тъй като тя винаги може да се разшири по-късно и мисля, че е чудесна идея да ви покажа как успях да я управлявам от Redux страна на нещата с няколко примера на код. Бъдете вдъхновени и го адаптирайте към собствените си нужди.

Защо става трудно да поддържам състоянието си Redux, докато приложението ми расте?

Redux е много страхотно средство и може да искате да го използвате по много причини. Може да се наложи да споделите някакво състояние от конкретен компонент, без да е необходимо да го предавате чрез реквизити, да получавате данни от сървърния API и да го споделяте в приложението си, да съхранявате история и да пътувате във времето през действията или дори да съхранявате състоянието на приложението в локалното съхранение на устройството на потребителя, за да го възстанови по-късно. Но никога не забравяйте, може да не се нуждаете от редукс.

Ако решите да използвате Redux, важно е да държите държавното състояние добре структурирано, така че да може да расте, докато приложението ви расте.

Когато имате проблеми със състоянието си Redux, има вероятност да имате проблеми с поддържането на цялото ви приложение, както и поради същите причини.

  • Имате ли твърде много създатели на глобални действия?
  • Имате ли огромен редуктор, който управлява всичко?
  • Имате ли конфликти между вашите действия или редуктори, които променят едно и също състояние?

В повечето случаи това е резултат от загуба на контрол и разбиране на поведението на приложението ви и в крайна сметка прекарвате повече време за отстраняване на грешки от кодиране. Истинска история.

Добавете вашите Redux файлове с вашата функция

Можете да разберете кога дадено приложение има добра архитектура, когато е разделено на няколко малки функции, които могат лесно да бъдат извлечени и публикувани в мениджъра на пакети и повторно използвани от друго приложение. Няма нищо по-лошо от това да прегледате стара директория на папки на проекта и да не можете да разберете дали някои функции или ресурси все още се използват някъде в приложението, защото някой е забравил да ги изтрие, докато рефакторира някакъв код.

Следователно, вие бихте искали да определите създателите и редукторите на своите действия Redux в функцията, която го консумира, за да следи какво се използва и къде се използва. Ако решите, че искате да премахнете цяла функция на приложението си, можете просто да го изключите и да изтриете цялата папка, която съдържа контейнерите и презентационните компоненти, редукторите, действията, ресурсите и т.н., и знаете, че ще бъде наред, защото състоянието е не е свързан с друга функция. Бързо, чисто и лесно.

С нарастването на приложението ви функции стават по-сложни. За да избегнете една-единствена функция, която управлява твърде много неща, трябва да ги разделите на няколко по-малки функции.

Една функция трябва да има всичко необходимо, за да работи самостоятелно. Той също трябва да има ограничен обхват и в идеалния случай да няма осведоменост за цялото приложение, но това понякога е трудно, тъй като компонентите на контейнерите ще трябва да са наясно с формата на състоянието Redux. Разбира се, можете да влагате функции в функции, стига да останат колкото е възможно по-самостоятелно и вложените да се използват само от прекия си родител.

По-долу „Книги“ е сцена, една функция на приложение. Той има подфункция ListItems, която е прост презентационен компонент. Сцената също има свои собствени действия и редуктори, определени в папката на функцията, където създателите на действията се използват от контейнерния компонент на функцията.

/ сцени
  /Книги
    / компоненти
      / ListItems
    /actions.js
    /index.js
    /reducer.js

По същия начин, по който съставяте функциите си на по-малки, вие също трябва да приложите това правило към вашите редуктори и да ги разделите, така че те да бъдат лесни за четене и поддържане. С такъв състав е за предпочитане да запазите структурата на цялото си състояние на дървения ред Redux, следвайки структурата на папките на вашите функции.

Създайте самостоятелни модули за данни

През повечето време компонентите на контейнерите консумират данни, които не са плътно свързани към конкретен компонент и може да се чудите къде трябва да бъдат дефинирани създателите на действията и редукторите. Начин за това е да създадете модули за данни, които да се грижат за отделни обекти от данни.

Основната отговорност на модула за данни е да управлява парче данни от вашето състояние Redux. Като пример можете да имате модул, който управлява потребителски обект, и друг за обект на книги. Можете да влагате модули за данни един в друг, стига да останат самостоятелни, по същия начин как се сглобяват функции.

Анатомията на модула за данни изглежда така:

Създатели на екшън

Те се грижат за бизнес логическата част. Те получават полезен товар, преобразувайки го при необходимост и връщат действие, което се изпраща за актуализиране на магазина Redux. В повечето проекти може да искате да използвате redux-thunk, за да имате асинхронни действия, като изпращане на заявки към сървърния API.

Редуктори и селектори

Редукторите обработват действия и актуализират състоянието Redux. В редукторите ви не трябва да има никаква логика, тъй като те трябва да останат чисти. Ако сте склонни да имате логически код, вместо това трябва да създадете друго действие.

Селекторите са важни, ако искате да филтрирате състоянието си, преди да ги използвате в компонентите на контейнера си. Можете да ги дефинирате във файла reducer.js, тъй като те са обвързани със същата част от състоянието.

API

Препоръчвам ви да създадете файл, наречен api.js, където можете да определите вашите мрежови заявки.

Виждах много проекти, при които единственият начин за изпращане на заявка за API беше чрез междинен софтуер Redux, което предполага, че всяко обаждане ще има влияние върху магазина Redux. Но това не е вярно, може да имате API обаждания, които не оказват влияние върху магазина, като обикновена POST заявка за изпращане на имейл, зависи как сте организирали приложението си. Но по тази причина предпочитам да ги определям в отделен файл.

След като модулът за данни е дефиниран, просто трябва да импортирате и комбинирате неговия редуктор с редуктора на данни, който сам се комбинира заедно с основния редуктор на вашата функция.

Сглобете няколко функции в едно

Сега, когато функциите ви са самостоятелни със собствените си действия и редуктори, трябва да ги сглобите, като приложите концепцията за състава на редуктора, където редукторът се нарича друг редуктор.

В примера по-долу има 2 модула за данни. Модулът за данни на потребителите е дефиниран в световен мащаб, което означава, че всяка функция може да импортира създател на действие от него и да го използва за извършване на промяна в потребителското дърво. Модулът за данни за книги обаче е вложен в сцената на Книги, тъй като се използва само в рамките на функцията Книги. За да работи всичко, трябва да сглобите основния редуктор на всяка детска функция в редуктора на функцията на родителя им. Можете да направите това с combReducers или ръчно, ако имате сложна структура на данни.

За всяка папка с данни имаме редуктор, който отговаря за комбинирането на всички модули за данни, дефинирани в тази папка. Въпреки че редукторът може да върне само един модул данни, при появата на допълнителни модули за данни в бъдеще да се добавят и за да се поддържа всичко последователно в приложението, по-добре е всички те да бъдат внесени и комбинирани в този единствен редуктор, така че редукторът на вашата функция може просто да ги импортирате и използвате, за да направите всички модули данни наведнъж. След това редукторът на функцията се използва от редуктора на функциите на прекия му родител или в коренния редуктор, ако е дефиниран на глобално ниво.

Ето как изглежда редукторът в сцени / Книги, капсулиращи модулите за данни:

В този пример редукторът улавя действия от модула за данни, за да настрои състоянието на зареждане, когато има заявка за зареждане на нови данни. Можете да се справите със същото действие в няколко редуктора или обратно, като мутирате това, което е уместно. Това ви помага да мащабирате разработката на приложението си, защото различните хора от вашия екип могат да работят върху различни функции и модули за данни, обработващи едни и същи действия, без да причиняват конфликти на сливане, докато се натъкнете на кода на другия.

След като правилно комбинирате редукторите заедно за всичките си функции, дървото на състоянието Redux на приложението ви трябва да изглежда така:

След като вашите редуктори са сглобени след тази структура, компонентите на контейнерите ви могат да се свържат с магазина Redux и да използват селекторите, които сте дефинирали по-рано, за да консумирате данните и да изпращате действия на вашата функция, за да направите промени в магазина.

Обобщавайки

Надявам се да не се страхувате повече, когато става дума за изграждане на силно мащабируем javascript уеб или мобилни приложения с Redux. Независимо колко голямо е приложението ви, следването на такава структура ще ви предпази от неочаквани неща, които да се случат и нарастващи проблеми.

Публикувах в моя акаунт в Github примерен проект, който следва тази структура: https://github.com/alexmngn/react-feedback-form

Чувствайте се свободни да добавите отговор по-долу или да се свържете директно с мен, ако имате въпроси, ще се радвам да ви помогна.

Още статии от мен

  • Как да организирате по-добре вашите приложения React?
  • Какви са основните разлики между ReactJS и React-Native?
  • Основната котло за удостоверяване на потребителите във вашето приложение React-Native

За мен

Здравей, аз съм Алексис! Аз съм разработчик на програми за Javascript, който програмирам повече от 15 години. Специализиран съм в архитектирането и разработването на много мащабируеми уеб и мобилни приложения, докато се наслаждавам на функционално програмиране. Наскоро започнах да използвам Twitter, можете да ме последвате тук: @alexmngn