Редукс · Введение

Опубликовано: 2022-03-10
Краткое резюме ↬ Redux — одна из самых популярных библиотек для фронтенд-разработки на сегодняшний день. Однако многие люди не понимают, что это такое и в чем его преимущества. Как указано в документации, Redux — это контейнер с предсказуемым состоянием для приложений JavaScript . Другими словами, это архитектура потока данных приложения, а не традиционная библиотека или фреймворк вроде Underscore.js и AngularJS.

В наши дни Redux — одна из самых популярных библиотек для фронтенд-разработки. Однако многие люди не понимают, что это такое и в чем его преимущества.

Как указано в документации, Redux — это контейнер с предсказуемым состоянием для приложений JavaScript. Другими словами, это архитектура потока данных приложения, а не традиционная библиотека или фреймворк вроде Underscore.js и AngularJS.

Дальнейшее чтение на SmashingMag

  • Почему вы должны рассмотреть React Native для своего мобильного приложения
  • Автоматизация тестирования приложений, игр и мобильного Интернета
  • Рендеринг на стороне сервера с помощью React, Node и Express
  • Примечания о клиентской доступности

Redux был создан Дэном Абрамовым примерно в июне 2015 года. Он был вдохновлен Flux от Facebook и языком функционального программирования Elm. Redux очень быстро стал популярным благодаря своей простоте , небольшому размеру (всего 2 КБ) и отличной документации. Если вы хотите узнать, как Redux работает внутри, и погрузиться в библиотеку, подумайте о том, чтобы пройти бесплатный курс Дэна.

Еще после прыжка! Продолжить чтение ниже ↓

Redux используется в основном для управления состоянием приложения. Подводя итог, Redux поддерживает состояние всего приложения в одном неизменном дереве состояний (объекте), которое нельзя изменить напрямую. Когда что-то меняется, создается новый объект (используя действия и редукторы). Ниже мы подробно рассмотрим основные концепции.

Чем он отличается от MVC и Flux?

Чтобы дать некоторое представление, давайте возьмем классический шаблон модель-представление-контроллер (MVC), поскольку большинство разработчиков знакомы с ним. В архитектуре MVC существует четкое разделение между данными (моделью), представлением (представлением) и логикой (контроллером). С этим есть одна проблема, особенно в крупномасштабных приложениях: поток данных является двунаправленным. Это означает, что одно изменение (пользовательский ввод или ответ API) может повлиять на состояние приложения во многих местах кода — например, на двустороннюю привязку данных. Это может быть трудно поддерживать и отлаживать.

Flux очень похож на Redux. Основное отличие состоит в том, что Flux имеет несколько хранилищ, которые изменяют состояние приложения, и транслирует эти изменения как события. Компоненты могут подписываться на эти события для синхронизации с текущим состоянием. В Redux нет диспетчера , который во Flux используется для трансляции полезной нагрузки зарегистрированным обратным вызовам. Еще одно отличие Flux в том, что доступно множество разновидностей, что создает некоторую путаницу и непоследовательность.

Преимущества Редукса

Вы можете спросить: «Зачем мне использовать Redux?» Отличный вопрос. Есть несколько преимуществ использования Redux в вашем следующем приложении:

  • Предсказуемость результата
    Всегда есть один источник правды, хранилище, без путаницы в том, как синхронизировать текущее состояние с действиями и другими частями приложения.
  • Ремонтопригодность
    Наличие предсказуемого результата и строгой структуры облегчает поддержку кода.
  • Организация
    Redux более строго относится к организации кода, что делает его более последовательным и удобным для работы в команде.
  • Рендеринг сервера
    Это очень полезно, особенно для начального рендеринга, для улучшения взаимодействия с пользователем или поисковой оптимизации. Просто передайте магазин, созданный на сервере, на сторону клиента.
  • Инструменты разработчика
    Разработчики могут отслеживать все, что происходит в приложении, в режиме реального времени, от действий до изменений состояния.
  • Сообщество и экосистема
    Это огромный плюс, когда вы изучаете или используете любую библиотеку или фреймворк. Наличие сообщества позади Redux делает его еще более привлекательным в использовании.
  • Простота тестирования
    Первое правило написания тестируемого кода — писать небольшие функции, которые делают только одну вещь и являются независимыми. Код Redux — это в основном функции, которые являются именно такими: маленькими, чистыми и изолированными.

Функциональное программирование

Как уже упоминалось, Redux был построен на основе концепций функционального программирования. Понимание этих концепций очень важно для понимания того, как и почему Redux работает именно так. Давайте рассмотрим основные концепции функционального программирования:

  • Он может обращаться с функциями как с объектами первого класса.
  • Он может передавать функции в качестве аргументов.
  • Он может управлять потоком, используя функции, рекурсии и массивы.
  • Он может использовать чистые, рекурсивные, функции высшего порядка, замыкания и анонимные функции.
  • Он может использовать вспомогательные функции, такие как карта, фильтрация и уменьшение.
  • Он может связывать функции вместе.
  • Состояние не меняется (т.е. неизменно).
  • Порядок выполнения кода не важен.

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

01-функциональное программирование-опт-предварительный просмотр
Пример функционального программирования (Изображение: Таня Бачук) (Посмотреть большую версию)

Вы увидите чистые функции, анонимные функции, замыкания, функции высшего порядка и цепочки методов, среди прочего, очень часто при работе с функциональным JavaScript. Redux активно использует чистые функции, поэтому важно понимать, что они из себя представляют.

Чистые функции возвращают новое значение на основе переданных им аргументов. Они не изменяют существующие объекты; вместо этого они возвращают новый. Эти функции не зависят от состояния, из которого они вызываются, и возвращают только один и тот же результат для любого предоставленного аргумента. По этой причине они очень предсказуемы.

Поскольку чистые функции не изменяют никаких значений, они не влияют на область действия или какие-либо наблюдаемые побочные эффекты, а это означает, что разработчик может сосредоточиться только на значениях, которые возвращает чистая функция.

Где можно использовать Redux?

Большинство разработчиков ассоциируют Redux с React, но его можно использовать с любой другой библиотекой представлений. Например, вы можете использовать Redux с AngularJS, Vue.js, Polymer, Ember, Backbone.js и Meteor. Тем не менее, Redux плюс React по-прежнему является наиболее распространенной комбинацией. Обязательно изучайте React в правильном порядке: лучшее руководство — это руководство Пита Ханта, которое очень полезно для разработчиков, которые только начинают работать с React и перегружены всем, что происходит в экосистеме. Усталость от JavaScript вызывает законную озабоченность у разработчиков интерфейса, как новичков, так и опытных, поэтому найдите время, чтобы изучить React или Redux правильно и в правильном порядке.

Одной из причин, по которой Redux так хорош, является его экосистема. Доступно так много статей, учебных пособий, промежуточного программного обеспечения, инструментов и шаблонов. Лично я использую шаблон Дэвида Зуковски, потому что в нем есть все необходимое для создания приложения JavaScript с помощью React, Redux и React Router. Предостережение: старайтесь не использовать шаблоны и стартовые наборы при изучении новых фреймворков, таких как React и Redux. Это сделает его еще более запутанным, потому что вы не поймете, как все работает вместе. Сначала изучите его и создайте очень простое приложение, в идеале в качестве побочного проекта, а затем используйте шаблоны для рабочих приложений, чтобы сэкономить время.

Строительные части Redux

Концепции Redux могут показаться сложными или причудливыми, но они просты. Помните, что библиотека составляет всего 2 КБ. Redux состоит из трех строительных частей: действий, хранилища и редукторов.

02-reux-data-flow-opt-предварительный просмотр
Поток данных Redux (Изображение: Таня Бачук) (Просмотреть большую версию)

Давайте обсудим, что делает каждый.

Действия

Короче говоря, действия — это события. Действия отправляют данные из приложения (взаимодействия с пользователем, внутренние события, такие как вызовы API и отправка форм) в магазин. Магазин получает информацию только из действий. Внутренние действия — это простые объекты JavaScript, которые имеют свойство type (обычно константное), описывающее тип действия и полезную нагрузку информации, отправляемой в хранилище.

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

Действия создаются с помощью создателей действий. Это звучит очевидно, я знаю. Это просто функции, которые возвращают действия.

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

Таким образом, вызывать действия в любом месте приложения очень просто. Используйте метод dispatch , например:

 dispatch(authUser(form));

Редукторы

Мы уже обсуждали, что такое редюсер в функциональном JavaScript. Он основан на методе уменьшения массива, где он принимает обратный вызов (редуктор) и позволяет вам получить одно значение из нескольких значений, сумм целых чисел или накопления потоков значений. В Redux редюсеры — это функции (чистые), которые принимают текущее состояние приложения и действие, а затем возвращают новое состояние. Понимание того, как работают редукторы, важно, потому что они выполняют большую часть работы. Вот очень простой редьюсер, который принимает текущее состояние и действие в качестве аргументов, а затем возвращает следующее состояние:

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

Для более сложных приложений возможно использование combineReducers() , предоставляемой Redux (действительно, рекомендуется). Он объединяет все редукторы в приложении в один индексный редуктор. Каждый редьюсер отвечает за свою часть состояния приложения, и параметр состояния у каждого редьюсера разный. combineReducers() значительно упрощает поддержку файловой структуры.

Если объект (состояние) изменяет только некоторые значения, Redux создает новый объект, значения, которые не изменились, будут ссылаться на старый объект, и будут созданы только новые значения. Это отлично подходит для производительности. Чтобы сделать его еще более эффективным, вы можете добавить Immutable.js.

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

Магазин

Store — это объект, который содержит состояние приложения и предоставляет несколько вспомогательных методов для доступа к состоянию, отправки действий и регистрации слушателей. Весь штат представлен одним магазином. Любое действие возвращает новое состояние через редьюсеры. Это делает Redux очень простым и предсказуемым.

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

Инструменты разработчика, путешествия во времени и горячая перезагрузка

Чтобы упростить работу с Redux, особенно при работе с крупномасштабным приложением, я рекомендую использовать Redux DevTools. Это невероятно полезно, так как показывает изменения состояния с течением времени, изменения в реальном времени, действия и текущее состояние. Это экономит ваше время и усилия, избегая текущего состояния и действий console.log .

03-redux-dev-tools-opt-preview
Redux DevTools (Посмотреть большую версию)

Redux имеет немного другую реализацию путешествий во времени, чем Flux. В Redux вы можете вернуться к предыдущему состоянию и даже изменить свое состояние с этого момента. Redux DevTools поддерживает следующие функции «путешествия во времени» в рабочем процессе Redux (думайте о них как о командах Git для вашего состояния):

  • Сброс : сбрасывает состояние, в котором был создан ваш магазин.
  • Revert : возвращается к последнему зафиксированному состоянию
  • Sweep : удаляет все отключенные действия, которые вы могли запустить по ошибке.
  • Commit : делает текущее состояние начальным.

Функция перемещения во времени неэффективна в производственной среде и предназначена только для разработки и отладки. То же самое касается DevTools.

Redux значительно упрощает тестирование, потому что он использует функциональный JavaScript в качестве основы, а небольшие независимые функции легко тестировать. Итак, если вам нужно что-то изменить в дереве состояний, импортируйте только один редюсер, отвечающий за это состояние, и протестируйте его изолированно.

Создайте приложение

В заключение этого вводного руководства давайте создадим очень простое приложение, используя Redux и React. Чтобы всем было легче следовать, я буду придерживаться старого доброго JavaScript, используя как можно меньше ECMAScript 2015 и 2016. Мы продолжим логику входа в систему, начатую ранее в этом посте. В этом примере не используются какие-либо оперативные данные, потому что цель этого приложения — показать, как Redux управляет состоянием очень простого приложения. Мы будем использовать CodePen.

1. Реагировать Компонент

Нам нужны некоторые компоненты и данные React. Давайте создадим простой компонент и отобразим его на странице. Компонент будет иметь поле ввода и кнопку (это очень простая форма входа). Ниже мы добавим текст, представляющий наше состояние:

См. Pen Intro to Redux Алекса Бачука (@abachuk) на CodePen.

См. Pen Intro to Redux Алекса Бачука (@abachuk) на CodePen.

2. События и действия

Давайте добавим Redux в проект и обработаем событие onClick для кнопки. Как только пользователь войдет в систему, мы отправим действие с типом LOGIN и значением текущего пользователя. Прежде чем мы сможем это сделать, мы должны создать хранилище и передать ему функцию-редуктор в качестве аргумента. На данный момент редьюсер будет просто пустой функцией:

См. Pen Intro to Redux — Шаг 2. События и действия Алекса Бачука (@abachuk) на CodePen.

См. Pen Intro to Redux — Шаг 2. События и действия Алекса Бачука (@abachuk) на CodePen.

3. Редукторы

Теперь, когда у нас есть действие, редюсер выполнит это действие и вернет новое состояние. Давайте обработаем действие LOGIN , возвращающее статус входа в систему, а также добавим действие LOGOUT , чтобы мы могли использовать его позже. Редуктор auth принимает два параметра:

  1. текущее состояние (которое имеет значение по умолчанию),
  2. Действие.

См. Pen Intro to Redux — Step 3. Reducers от Алекса Бачука (@abachuk) на CodePen.

См. Pen Intro to Redux — Step 3. Reducers от Алекса Бачука (@abachuk) на CodePen.

4. Отображение текущего состояния

Теперь, когда у нас есть начальное состояние (значение по умолчанию в редюсере) и готовый компонент React, давайте посмотрим, как выглядит состояние. Лучшей практикой является передача состояния дочерним компонентам. Поскольку у нас есть только один компонент, давайте передадим состояние приложения как свойство компонентам auth . Чтобы все работало вместе, мы должны зарегистрировать прослушиватель хранилища с помощью вспомогательного метода subscribe , ReactDOM.render в функцию и передав ее в store.subscribe() :

См. Pen Intro to Redux — Шаг 4. Отображение текущего состояния Алекса Бачука (@abachuk) на CodePen.

См. Pen Intro to Redux — Шаг 4. Отображение текущего состояния Алекса Бачука (@abachuk) на CodePen.

5. Войти и выйти

Теперь, когда у нас есть обработчики действий входа и выхода, давайте добавим кнопку выхода из системы и отправим действие LOGOUT . Последний шаг — выбрать, какая кнопка отображать вход в систему или выход из системы, переместив этот вход за пределы метода рендеринга и отобразив переменную ниже:

См. Pen Intro to Redux — Шаг 5. Вход/выход от Alex Bachuk (@abachuk) на CodePen.

См. Pen Intro to Redux — Шаг 5. Вход/выход от Alex Bachuk (@abachuk) на CodePen.

Заключение

Redux набирает обороты с каждым днем. Он успешно используется многими компаниями (Uber, Khan Academy, Twitter) и во многих проектах (Apollo, WordPress' Calypso). Некоторые разработчики могут жаловаться на большие накладные расходы. В большинстве случаев требуется больше кода для выполнения простых действий, таких как нажатия кнопок или простые изменения пользовательского интерфейса. Redux не идеально подходит для всего. Должен быть баланс. Возможно, простые действия и изменения пользовательского интерфейса не обязательно должны быть частью магазина Redux и могут поддерживаться на уровне компонентов.

Несмотря на то, что Redux может быть не идеальным решением для вашего приложения или фреймворка, я настоятельно рекомендую проверить его, особенно для приложений React.

Кредиты изображения на первой странице: Линн Фишер, @lynnandtonic