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

0
5658
Добавить в избранное

Хватит ждать, пора действовать! Изучаем действия в приложении на Redux, сразу применяя теоретический материал на практике.

Посмотрите знакомство с Redux и первое приложение.

Дизайн макета обновлён. При нажатии на любую из кнопок для обновления состояния пользователь чувствует взаимодействие с приложением:

Redux на практике: осваиваем действия в приложении
Пример работы в GIF

Что есть действие в Redux?

При посещении банка кассир узнаёт о вашем намерении снять деньги. WITHDRAWAL_MONEY – оно же является действием. Чтобы получить деньги, нужно взаимодействовать с кассиром.

В отличие от setState(), единственный способ обновить состояние в Redux – сообщить об этом reducer:

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

Представим, что номер банковского счета не нужно сообщать, и тогда этой информации становится достаточно.

Вы не можете серьезно модифицировать функцию type. Дополнительная информация задаётся в payload:

Обработка данных в редукторах

Мы говорили, что reducer принимает два значения – state и action. Простой reducer выглядит так:

Чтобы reducer обработал функцию, нужно задать ему инструкцию, используя switch:

В данном примере switch запустит механизм исполнения действия в приложении. Допустим, у вас было 2 кнопки:

При нажатии на первую кнопку приложение переходит в состояние isOpen:

А при нажатии на вторую обновляется поле isClicked:

В Redux не получится использовать setState(): сначала нужно сообщить о действии.

№1

№2

В Redux-приложении всё проходит через редуктор. Поэтому мы ввели поле action.type, чтобы reducer определял нужное действие:

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

Важно обрабатывать каждый тип по отдельности. Для этого и нужен switch.

Обработка действия в приложении

Для обновления состояния приложений нужно сообщать action, неважно каким способом. При каждом нажатии кнопки нам нужно отправить действие:

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

Посмотрите, как это будет работать с каждой из кнопок.

React

React-redux

Elm

Все действия имеют одно и то же поле type. Как в банке: пополнение счёта производилось бы на разные суммы. Общая функция DEPOSIT_MONEY, разное количество amount.

Дублирование кода

Давайте уменьшим количество повторяющегося кода. Для этого в Redux есть Action Creators. Это функции, которые создают объекты-действия. Например, в нашем случае можно создать функцию setTechnology, принимающую аргумент «текст»:

Объединяем пройденное

Итак, когда вы приходите в банк, кассир сидит за столом и ожидает клиентов, а сейф с деньгами ждёт своего часа в соседней комнате. В Redux каждый участник цепочки (reducer, action, store) тоже находится на своём месте – в отдельной папке. Обычно создают 3 папки:

Redux

В каждой из папок создаем файл index.js, что позволит начать работу каждой функции. Теперь будем работать с нашим приложением из статьи.

store/index.js

Это работает так же, как и ранее. Отличие в том, что хранилище создаётся в отдельном index.js файле. Если нам нужен store, будем писать:

App.js

В чем отличия? В четвертой строке хранилище импортируется из собственной «комнаты». Кроме того, здесь есть компонент, который отвечает за работу кнопок.

Redux

Следующая особенность в том, что приложение возвращает массив. Это стало доступно в React 16.

react

Так это работает для компонента App.js.

Реализация ButtonGroup проще:

ButtonGroup не имеет состояния. Он просто принимает массив названий технологий и с помощью map генерирует button для каждого элемента. В данном примере передаётся массив [«React», «Elm», «React-redux»]. У кнопок есть несколько атрибутов:

  • className для стиля;
  • key, который вы будете постоянно забывать;
  • атрибут данных data-btn для более простого извлечения некоторых значений из элементов.

Сгенерированная кнопка выглядит так:

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

Так происходит потому, что мы не настроили обработчик кликов. Внутри функции render определим действие для onClick:

Хорошо. Теперь определим dispatchBtnAction.

Не забудьте, что основная цель обработчика – послать действие на обработку. Если нажать на кнопку «React», произойдет следующее действие:

А если нажать на «React-Redux»:

Вот так выглядит функция dispatchBtnAction:

Имеет ли смысл код выше?

e.target.dataset.tech получит атрибут данных с кнопки data-tech. Таким образом, константа tech будет хранить текст кнопки. store.dispatch() – способ
отправки действия в приложении на Redux, а setTechnology() – генератор действий, написанный нами ранее. То есть store.dispatch принимает, а setTechnology – создаёт.

Код на изображении ниже должен помочь разобраться в происходящем:

Что происходит после отправки действия?

Для начала несложный вопрос. Что происходит после нажатия кнопки (и отправки действия)? Какой участник появляется в цепочке Redux?

Правильный ответ – кассир. Здесь действия после отправки проходят через редуктор. Чтобы показать это, залоггируем все действия в приложении, проходящие через него:

reducers/index.js

Reducer возвращает начальное состояние. Через console.log() можно посмотреть, что происходит при нажатии на кнопку.

Действия учитываются при нажатии, значит, все проходит через редукторы, как мы и говорили.

Но есть один нюанс. При запуске приложения учитывается лишнее действие:

Это обычная инициализация, не оказывающая негативного влияния на работу программы.

Создание счётчика редуктора

До текущего момента мы писали приложение, которое ничего не делает. Как кассир, который не умеет делать WITHDRAW_MONEY. Что мы хотим от редуктора? При создании хранилища мы передали initialState в createStore.

Когда пользователь нажимает на любую из кнопок, редуктор должен модифицировать состояние:

Цель последнего действия – обновление состояния. Будем использовать switch для обработки разных действий:

Но теперь в фокусе switch будет action.type. Почему? В качестве операций, которые может выполнить кассир – снять наличные, внести на счет, etc. Наш редуктор выполняет действие SET_TECHNOLOGY, но позднее могут быть и другие. Этот единственный case будет отвечать за переключение технологии на любое значение.

Не забывайте, что во всех прочих случаях не стоит выполнять никаких действий. Нужно просто вернуть текущее состояние state.

Кассир (редуктор) понимает, что вы хотите сделать, но не возвращает никакого ответа. Исправим это:

Что только что произошло – объясняем ниже.

Никогда не меняйте состояние внутри редукторов

Первое, что хочется сделать – изменить state и вернуть его (код ниже). Если вы уже знакомы с хорошим стилем в React, то знаете, что это ошибка:

Редуктор и вернул вот это:

Вместо изменения состояния мы возвращаем новый объект. Он имеет все свойства предыдущего, но находится в другом пространстве.

Кроме того, редукторы должны быть чистыми функциями без вызовов API, обновления значений. Теперь воображаемый кассир выдаёт нам деньги. Попробуем нажимать на кнопки. Работает? Нет! По крайней мере, текст не обновляется. В чём дело?

Обновление хранилища

После снятия денег обычно приходит сообщение о совершении операции. В Redux тоже следует настроить получение уведомлений об успешном обновлении состояния.

В каждом хранилище есть метод store.subscribe(). Он вызывается всякий раз, когда изменяется состояние.

Итак, нам нужно обновить элемент на странице. Для этого используем render.

Посмотрим, как это работает в index.js:

Приложение берёт компонент <App /> и отображает его в DOM.

Используя принципы ES6, функцию можно упростить.

После каждого успешного обновления <App /> будет повторно отображаться с новыми значениями состояния:

Работает!

Заключение

Что нужно было усвоить в этой главе:

  • В отличие от setState() в React, единственный способ обновления состояния приложения Redux – отправка действия.
  • Действие описывается с помощью JavaScript-объекта с информацией о типе.
  • В приложении Redux каждое действие проходит через редуктор.
  • Используя оператор switch, можно обрабатывать разные типы действий в редукторе.
  • Action Creators – это функции, возвращающие объекты действий.
  • Основные участники цепочки Redux живут в своих папках.
  • Вы не должны изменять состояние. Нужно возвращать новую копию состояния.
  • Чтобы подписаться на сохранение обновлений, используйте метод store.subscribe().

Больше информации вы найдете здесь.

Интересуетесь фронтендом?

Подпишитесь на нашу рассылку, чтобы получать больше интересных материалов:

И не беспокойтесь, мы тоже не любим спам. Отписаться можно в любое время.




Добавить комментарий