10 съвета за по-добра архитектура Redux

Мандаринова патица - Малкълм Карлау (CC-BY-2.0)

Когато започнах да използвам React, Redux нямаше. Имаше само архитектурата на Flux и около дузина конкурентни реализации от нея.

Сега в React има два ясни победителя за управление на данни: Redux и MobX, а последният дори не е реализация на Flux. Redux се хвана толкова много, че вече не се използва само за React. Можете да намерите архитектурни реализации Redux за други рамки, включително Angular 2. Вижте например ngrx: store.

Странична бележка: MobX е готин и вероятно бих го избрал за Redux за прости потребителски интерфейси, тъй като е по-малко сложен и по-малко многословен. Имайки предвид това, има някои важни характеристики на Redux, които MobX не ви дава и е важно да разберете какви са тези функции, преди да решите какво е подходящо за вашия проект.
Странична забележка: Relay и Falcor са други интересни решения за управление на състоянието, но за разлика от Redux и MobX, те трябва да бъдат подкрепени съответно от GraphQL и Falcor Server и всички състояния на релето съответстват на някои поддържани от сървъра данни. AFAIK нито предлага добра история за преходно управление на държавата само от страна на клиента. Възможно е да можете да се възползвате от предимствата на двете, като смесвате и сравнявате Relay или Falcor с Redux или MobX, разграничавайки състоянието само за клиент и поддържаното от сървъра състояние. Долен ред: Днес няма ясен единичен победител за управление на държавата на клиента. Използвайте подходящия инструмент за работата под ръка.

Дан Абрамов, създателят на Redux, направи няколко страхотни курса по темата:

  • Първи стъпки с Redux
  • Изграждане на приложения с Idiomatic Redux

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

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

1. Разберете ползите от Redux

Има няколко важни цели за Redux, които трябва да имате предвид:

  1. Детерминиран изглед на рендери
  2. Детерминирано възпроизвеждане на държавата

Детерминизмът е важен за проверка на приложението и диагностициране и коригиране на грешки. Ако изгледите и състоянието на приложението ви не са детерминирани, не е възможно да знаете дали изгледите и състоянието винаги ще бъдат валидни или не. Може дори да кажете, че недетерминизмът сам по себе си е грешка.

Но някои неща са по своята същност недетерминирани. Неща като времето за въвеждане от потребителя и мрежовия вход / изход. И така, как можем да разберем дали кодът ни наистина работи? Лесно: Изолация.

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

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

Когато новак мисли за създаване на изглед, той може да си помисли: „Този ​​бит се нуждае от модела на потребителя, така че ще пусна асинхронна заявка, за да го получа и когато обещанието се разреши, ще актуализирам потребителския компонент с тяхното име. Това малко неща изисква задължителни предмети, така че ще го вземем и когато обещанието се разреши, ще преминем към тях и ще ги изведем на екрана. "

Има няколко основни проблема с този подход:

  1. Никога не разполагате с всички данни, които са ви необходими, за да направите цялостния изглед във всеки даден момент. Всъщност не започвате да извличате данни, докато компонентът не започне да върши своята работа.
  2. Различни задачи за извличане могат да влизат в различно време, коварно променяйки реда, в който нещата се случват в последователността на представяне на изглед. За да разберете истински последователността на визуализация, трябва да имате знания за нещо, което не можете да предвидите: продължителността на всяка заявка за асинхронизация. Поп тест: В горния сценарий какво прави първо, потребителският компонент или елементите със задачи? Отговор: Това е състезание!
  3. Понякога слушателите на събития ще мутират състоянието на изгледа, което може да предизвика друго изобразяване, като допълнително усложнява последователността.

Основният проблем със съхранението на вашите данни в състояние на изглед и предоставяне на достъп на слушателите на асинхронни събития да мутират това състояние на изглед е следният:

„Недетерминизъм = паралелна обработка + споделено състояние“
~ Мартин Одерски (дизайнер на Scala)
Смесването на извличането на данни, манипулирането на данни и загрижеността за визуализация е рецепта за пътуващи във времето спагети.

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

Това, което прави архитектурата на потока, е да налага строго разделение и последователност, които се подчиняват на тези правила всеки път:

  1. Първо, ние влизаме в известно, фиксирано състояние ...
  2. След това правим гледката. Нищо не може да промени състоянието отново за този цикъл на визуализация.
  3. Като се има предвид същото състояние, изгледът винаги ще се изобразява по същия начин.
  4. Слушателите на събития слушат за въвеждане на потребител и за обработка на мрежови заявки. Когато ги получат, действията се изпращат до магазина.
  5. Когато се изпраща действие, състоянието се актуализира до ново известно състояние и последователността се повтаря. Само изпратените действия могат да докоснат държавата.

Това е Flux накратко: Еднопосочна архитектура на потока от данни за вашия потребителски интерфейс:

Flux Architecture

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

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

Обектите за действие изглеждат така:

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

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

Това има важни последици:

  1. Лесна проверка
  2. Лесно отмяна / повтор
  3. Отстраняване на грешки във времето за пътуване
  4. Дълготрайност - Дори и държавата да бъде заличена, ако имате запис на всяка транзакция, можете да я възпроизведете.

Кой не иска да владее пространство и време? Транзакционното състояние ви дава пътуващи във времето суперсили:

Показване на плъзгача на историята на инструментите Redux dev

2. Някои приложения не се нуждаят от Redux

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

Ако:

  • Потребителските работни процеси са прости
  • Потребителите не си сътрудничат
  • Не е необходимо да управлявате събития от страна на сървъра (SSE) или уеб сокети
  • Извличате данни от един източник на данни на изглед

Може да се окаже, че последователността от събития в приложението вероятно е достатъчно проста, че ползите от транзакционното състояние не си струват допълнителните усилия.

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

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

Ако:

  • Потребителските работни процеси са сложни
  • Приложението Ви има голямо разнообразие от работни процеси на потребителите (имайте предвид както обикновените потребители, така и администраторите)
  • Потребителите могат да си сътрудничат
  • Използвате уеб сокети или SSE
  • Зареждате данни от множество крайни точки, за да изградите един изглед

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

Какво общо имат уеб сокетите и SSE? Докато добавяте още източници на асинхронен I / O, става по-трудно да разберете какво се случва в приложението с неопределено управление на състоянието. Детерминираното състояние и запис на транзакциите в държавата радикално опростяват приложения като това.

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

3. Разберете редуктори

Redux = Flux + функционално програмиране

Flux предписва еднопосочен поток на данни и транзакционно състояние с обекти за действие, но не казва нищо за това как да боравите с обектите за действие. Точно там идва Redux.

Основният градивен елемент на управлението на състоянието Redux е редукторната функция. Какво е функция за редуктор?

Във функционалното програмиране общата полезна програма "намаляване ()" или "сгъване ()" се използва за прилагане на функция на редуктор към всяка стойност в списък със стойности, за да се натрупа единична изходна стойност. Ето пример за редуктор за сумиране, приложен към масив JavaScript с „Array.prototype.reduce ()“:

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

Нека превърнем редуктора за сумиране по-горе в редуктор в стил Redux:

Сега можем да го приложим към някои тестови действия:

4. Редукторите трябва да са чисти функции

За да се постигне детерминирано възпроизвеждане на състоянието, редукторите трябва да са чисти функции. Без изключения. Чиста функция:

  1. Имайки един и същ вход, винаги връща един и същ изход.
  2. Няма странични ефекти.

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

Редукторите трябва вместо това да върнат нов обект. Можете да направите това например с „Object.assign ({}, state, {thingToChange})“.

Параметрите на масива също са референции. Не можете просто да `.push ()` нови елементи в масив в редуктор, тъй като `.push ()` е мутираща операция. По същия начин са и. .Pp () `,` .shift () `,` .unshift () `,` .reverse () `,` .splice () `и всеки друг мутационен метод.

Ако искате да сте сигурни с масиви, трябва да ограничите операциите, които извършвате в състояние, до методите за безопасен достъп. Вместо `.push ()`, използвайте `.concat ()`.

Разгледайте случая "ADD_CHAT" в този чат редуктор:

Както можете да видите, нов обект се създава с `Object.assign ()` и ние добавяме към масива с `.concat ()` вместо `.push ()`.

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

Има много повече чисти функции от тази. Ако ще използвате Redux за производствени приложения, наистина се нуждаете от добро разбиране за това какви са чистите функции и други неща, които трябва да имате предвид (като например справяне с времето, регистриране и случайни числа). За повече информация вижте “Овладяване на интервюто с JavaScript: Какво е чиста функция?”.

5. Помнете: редукторите трябва да са единственият източник на истината

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

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

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

С други думи, без единния принцип на истината, вие потенциално губите:

  • Детерминиран визуализация на изгледа
  • Детерминирано възпроизвеждане на състоянието
  • Лесно отмяна / повтор
  • Отстраняване на грешки във времето за пътуване
  • Лесна проверка

Или Redux, или не Redux вашата държава. Ако го направите наполовина, бихте могли да отмените всички предимства на Redux.

6. Използвайте константи за типове действия

Обичам да се уверя, че действията са лесни за проследяване до редуктора, който ги използва, когато преглеждате историята на действията. Ако всичките ви действия имат кратки общи имена като „CHANGE_MESSAGE“, става по-трудно да разберете какво се случва в приложението ви. Ако обаче типовете действия имат по-описателни имена като „CHAT :: CHANGE_MESSAGE“, очевидно е много по-ясно какво се случва.

Освен това, ако направите печатна грешка и изпратите неопределена константа за действие, приложението ще хвърли грешка, за да ви предупреди за грешката. Ако направите печатна грешка с низ от тип действие, действието ще се провали безшумно.

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

  • Дръжте имената последователни
  • Бързо разберете API на редуктора
  • Вижте какво се е променило в заявките за изтегляне

7. Използвайте Създателите на действия, за да развържете логиката на действие от повикващите

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

И така, къде е доброто място за справяне с нечиста логика като тази, без да я повтаряте навсякъде, където трябва да използвате действието? В създател на действие.

Създателите на действията имат и други предимства:

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

Нека използваме създател на действие, за да генерираме „ADD_CHAT“ обект на действие:

Както можете да видите по-горе, ние използваме cuid за генериране на произволни идентификационни номера за всяко съобщение в чата и `Date.now ()` за генериране на времева марка. И двете са нечисти операции, които не са безопасни за изпълнение в редуктора - но е напълно добре да ги стартирате в създателите на действия.

Намалете котлона с създателите на действията

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

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

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

За по-големи редуктори това може да нарасне до много котлони. Много от редукторите, които съм изградил, могат да станат много по-сложни от това, с много излишен код. Ами ако можем да сринем всички прости действия за промяна на собствеността заедно?

Оказва се, че е лесно:

Дори с допълнителното разстояние и допълнителния коментар тази версия е по-къса - и това е само в два случая. Спестяванията наистина могат да се сумират.

Не е ли превключването ... случаят опасен? Виждам падане през!

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

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

Redux добре използва `switch..case`. Официално променям съветите си по въпроса. Докато следвате простичките правила по-горе (дръжте превключвателите малки и фокусирани и се връщайте от всеки случай със собственото си тяло), изявленията за превключване са наред.

Може би сте забелязали, че тази версия изисква различен полезен товар. Ето тук влизат създателите на вашите действия:

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

8. Използвайте настройките по подразбиране ES6 за документация за подпис

Ако използвате Tern.js с плъгин за редактор (наличен за популярни редактори като Sublime Text и Atom), той ще прочете тези задания по подразбиране ES6 и ще изведе необходимия интерфейс на вашите създатели на действия, така че когато ги извиквате, можете да получите intellisense и автоматично довършване. Това сваля когнитивното натоварване от разработчиците, тъй като няма да трябва да запомнят необходимия тип полезен товар или да проверяват изходния код, когато забравят.

Ако не използвате плъгин за извода за тип, като Tern, TypeScript или Flow, трябва да бъдете.

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

  1. Не е нужно да използвате Flow или TypeScript, за да работите: Вместо това използвате стандартен JavaScript.
  2. Ако използвате TypeScript или Flow, поясненията са излишни с заданията по подразбиране, тъй като и TypeScript и Flow извеждат типа от заданието по подразбиране.
  3. Намирам го за много по-четим, когато има по-малко синтактичен шум.
  4. Получавате настройки по подразбиране, което означава, че дори и да не спирате изграждането на CI на грешки от типа (ще се изненадате, много проекти не правят), никога няма да имате случайно „неопределен“ параметър, дебнещ във вашия код.

9. Използвайте селектори за изчислено състояние и отделяне

Представете си, че създавате най-сложното приложение за чат в историята на чат приложенията. Написахте 500k реда код и ТОГА екипът на продуктите ви подхвърли ново изискване за функция, което ще ви принуди да промените структурата на данните на вашата държава.

Няма нужда да се паникьосвате. Бяхте достатъчно умни, за да отделите останалата част от приложението от формата на държавата си с селектори. Куршум: изкривен.

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

export const getViewState = state => състояние;

Да, знам. Това е толкова просто, че дори не си струва същност Може би си мислите, че сега съм луда, но помните онзи куршум, който избягвахме преди? Ами ако искаме да добавим някакво изчислено състояние, като пълен списък на всички потребители, които са разговаряли по време на тази сесия? Нека го наречем „наскороActiveUsers“.

Тази информация вече се съхранява в сегашното ни състояние, но не по начин, който е лесен за хващане. Нека да продължим и да го вземем в „getViewState ()“:

Ако поставите цялото си изчислено състояние в селектори, вие:

  1. Намалете сложността на вашите редуктори и компоненти
  2. Отделете останалата част от приложението си от състоянието си
  3. Спазвайте принципа на единния източник на истина, дори и в рамките на вашия редуктор

10. Използвайте TDD: Първо напишете тестове

Много проучвания сравняват теста първо с методологиите след тест и изобщо без тестове. Резултатите са ясни и драматични: Повечето от проучванията показват между 40–80% намаление на грешки в доставката в резултат на писане на тестове, преди да внедрите функции.

TDD може ефективно да намали плътността на вашата грешка при доставката наполовина и има много доказателства, които да подкрепят това твърдение.

Докато писах примерите в тази статия, започнах всички с единични тестове.

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

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

Ето как ги използвах:

Забележка: Използвам лента за единични тестове поради нейната простота. Имам и опит от 2-3 години с Мока и Жасмин и различен опит с много други рамки. Трябва да можете да адаптирате тези принципи към каквато и рамка да изберете.

Обърнете внимание на стила, който съм разработил, за да опиша вложени тестове. Вероятно благодарение на моя опит, използващ Jasmine и Mocha, обичам да започвам, като описвам компонента, който тествам, във външен блок, а след това във вътрешни блокове, описвам какво преминавам към компонента. Вътре правя прости твърдения за еквивалентност, които можете да правите с функциите на deepEqual () или toEqual () на вашата тестваща библиотека.

Както можете да видите, използвам изолирани тестови състояния и фабрични функции вместо помощни програми като `beforeEach ()` и `afterEach () ', което избягвам, защото те могат да насърчат неопитни разработчици да използват споделено състояние в тестовия пакет (това е лошо) ,

Както вероятно сте се досетили, имам три различни вида тестове за всеки редуктор:

  1. Тестове за директни редуктори, за които току-що видяхте пример. Те по същество тестват, че редукторът създава очакваното състояние по подразбиране.
  2. Тестове на създателите на действия, които тестват всеки създател на действие, като прилагат редуктора към действието, използвайки някакво предварително определено състояние като начална точка.
  3. Селекторни тестове, които тестват селекторите, за да се гарантира, че всички очаквани свойства са там, включително изчислени свойства с очаквани стойности.

Вече видяхте тест за редуктор. Нека разгледаме някои други примери.

Тестове за създатели на действия

Този пример е интересен поради няколко причини. Създателят на действие `addChat () не е чист. Това означава, че ако не преминете в отмяна на стойността, не можете да направите конкретно очакване за всички произведени свойства. За да се справим с това, използвахме тръба, която понякога използвам, за да избегна създаването на допълнителни променливи, които всъщност не ми трябват. Използвах го, за да игнорирам генерираните стойности. Все още се уверяваме, че съществуват, но не ни интересува какви са стойностите. Обърнете внимание, че дори не проверявам типа. Ние се доверяваме на типа изводи и стойности по подразбиране, за да се погрижим за това.

Една тръба е функционална програма, която ви позволява да затворите някаква входна стойност чрез поредица от функции, всяка от които приема резултата от предишната функция и я трансформира по някакъв начин. Използвам lodash pipe от `lodash / fp / pipe`, което е псевдоним за` lodash / flow`. Интересното е, че самата `pipe () 'може да бъде създадена с редукторна функция:

Склонен съм да използвам `pipe () 'много в редукторните файлове, както и за опростяване на състоянието на преходи. Всички преходи на състоянието са в крайна сметка потоци от данни, преминаващи от едно представяне на данни към друго. Точно в това е „pipe ()“.

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

Селекторни тестове

И накрая, тестваме селекторите на състоянието и се уверяваме, че изчислените стойности са правилни и че всичко е както трябва да бъде:

Забележете, че в този тест използвахме „Array.prototype.reduce ()“, за да намалим над няколко примерни действия „addChat ()“. Едно от страхотните неща за редукторите Redux е, че те са просто редовни редукторни функции, което означава, че можете да правите с тях всичко, което бихте направили с всяка друга функция на редуктора.

Нашата `очаквана` стойност проверява дали всички наши обекти за чат са в дневника и дали наскоро активните потребители са посочени правилно.

Не е много друго да се каже за това.

Правила за редукс

Ако използвате Redux правилно, ще получите големи ползи:

  • Елиминирайте грешките в зависимост от времето
  • Активиране на детерминирани рендери на изглед
  • Активиране на възпроизвеждане на детерминирано състояние
  • Активиране на лесни функции за отмяна / повтор
  • Опростете отстраняване на грешки
  • Станете пътник във времето

Но за да работи всичко това, трябва да запомните някои правила:

  • Редукторите трябва да са чисти функции
  • Редукторите трябва да бъдат единственият източник на истина за тяхното състояние
  • Състоянието на редуктора винаги трябва да бъде сериализирано
  • Редукторът не трябва да съдържа функции

Имайте предвид също:

  • Някои приложения не се нуждаят от Redux
  • Използвайте константи за типове действия
  • Използвайте създателите на действия, за да отделите логиката на действие от обаждащите се
  • Използвайте ES6 параметрите по подразбиране за самоописване на подписите
  • Използвайте селектори за изчислено състояние и отделяне
  • Винаги използвайте TDD!

Наслади се!

Готови ли сте да изравните уменията си Redux с DevAnywhere?

Научете разширено функционално програмиране, React и Redux с менторство 1: 1. Членове на доживотния достъп, вижте функционалното програмиране и уроците Redux. Не забравяйте да гледате серията Shotgun и возете пушка с мен, докато създавам истински приложения с React и Redux.

https://devanywhere.io/

Ерик Елиът е автор на „Програмиране на JavaScript приложения“ (O’Reilly) и съосновател на DevAnywhere.io. Той е допринесъл за софтуерни преживявания за Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN, BBC и най-добрите звукозаписни артисти, включително Usher, Frank Ocean, Metallica и много други.

Той работи където си поиска с най-красивата жена в света.