Легко управлять состоянием открытия и закрытия диалогов

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

В этой статье я расскажу, как мы можем использовать Redux в React, чтобы контролировать, должны ли модальные окна быть видимыми. Сначала давайте рассмотрим пример приложения, а затем перейдем к подходу с использованием Redux, чтобы сэкономить нам много времени и сократить невероятное количество кода в наших компонентах.

Приложение

Приложение, которое мы будем использовать, представляет собой простую кнопку, которая открывает модальное окно, предлагающее пользователю нажать либо Да, либо Нет:

В этом подходе мы контролируем модальную видимость с помощью свойства isOpen, которое определяется непосредственно в MainComponent. Если свойство IsOpen равно true, будет показано модальное окно. В противном случае он будет скрыт.

В этом подходе нет никаких проблем, если мы используем это модальное окно только в одном компоненте. Если мы попытаемся использовать это модальное окно в других компонентах, как в случае YesNoModal, такой подход может привести к большому дублированию кода.

Каждый раз, когда мы используем это модальное окно, нам придется дублировать весь код, который контролирует открытое состояние модального окна. Каждый компонент, использующий это модальное окно, должен будет контролировать состояние, определяя свойство IsOpen.

Что, если бы мы могли вызвать какое-то действие, чтобы показать / скрыть это модальное окно и централизовать его контроль состояния? Давайте для этого воспользуемся Redux.

Как работает Redux

Глобальное управление государством может быть очень сложным. Redux помогает нам лучше справляться с управлением состоянием. Вкратце, Redux - это инструмент, который позволяет нам централизовать состояние / логику нашего приложения React. Это отличная новость, поскольку мы не хотим делегировать управление модальным состоянием каждому компоненту, который в нем нуждается.

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

Действия - это события, которые будут вызывать наши компоненты, чтобы остальная часть приложения знала, что мы хотим обновить какое-то состояние. В нашем случае вызовет какое-то действие, которое сообщает нашему состоянию, что нам нужно показать / скрыть YesNoModal.

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

И последнее, но не менее важное: хранилище - это механизм, в котором хранится все глобальное состояние приложения. Мы обновляем это состояние, вызывая наши действия, и обрабатываем их в редукторах.

Трудно объяснить, как работает Redux, в нескольких строках текста, но я обещаю вам, что это станет намного понятнее, когда мы увидим какой-нибудь код.

Установка Redux

Начнем с установки Redux:

npm install redux -s

Помимо самого Redux, давайте также установим response-redux, официальную привязку для React, которая помогает нашим компонентам узнавать, когда глобальное состояние изменилось, и повторно отображает его в соответствии с этим изменением:

npm install redux-react -s

Редуктор модалов

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

Редуктор состоит из объекта начального состояния и функции, которая будет вызываться, когда нам нужно внести некоторые изменения в состояние. Функция modalsStore получает состояние и действие в качестве параметра. Действие сообщает, какие изменения мы должны внести в свое состояние.

Если тип действия - ShowYesNoModal, мы возвращаем новое состояние, устанавливая значение showYesNoModal на true, указывая, что мы хотим показать модальное окно. Как только модальное окно открыто, мы можем закрыть его, отправив действие с типом HideYesNoModal, возвращая новое состояние с помощью свойства showYesNoModal = false.

Чтобы подключить этот редуктор к нашим компонентам, нам нужно внести некоторые изменения в файл index.js:

По сути, мы создаем магазин и подключаем его к нашим компонентам, оборачивая наше приложение компонентом Provider. Наши компоненты теперь могут отправлять действия и подписываться на изменения состояния. Обратите внимание, что мы можем объединить несколько редукторов. В этом примере у нас есть только modalReducer, но могут быть notificationReducer, alertReducer и т. Д.

Теперь мы можем подключить наш MainComponent и начать отправку действий, чтобы показать YesNoModal:

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

Но откуда взялась эта showYesNoModal функция ? Эта функция передается в props, когда мы подключаем mapDispatchtoProps к нашему компоненту в строке 36. По сути, мы отправляем действие типа ShowYesNoModal, которое будет захвачено нашим редуктором и инициирует изменение состояния.

Теперь нам просто нужно подписаться на это изменение состояния в самом YesNoModal, чтобы показать модальное окно:

Когда мы сопоставляем состояние с реквизитами (строка 33), мы просто подписываемся на любое изменение состояния в глобальном хранилище. Функция mapStateToProps получает объект глобального состояния и сопоставляет его с другим объектом, содержащим опору, которая управляет модальной видимостью.

Помимо свойства showModal, компонент получает функцию с именем closeModal. После вызова он отправит действие с типом HideYesNoModal, которое будет захвачено нашим редуктором и обновит состояние, установив для свойства, управляющего видимостью модального окна, значение false.

Вот и все: теперь мы управляем нашим модальным окном, используя глобальное состояние, управляемое Redux. В этот момент вы, вероятно, спрашиваете себя: «Зачем мне использовать Redux, если я в конечном итоге написал больше кода для достижения в основном того же результата?»

В приведенном выше примере у нас есть только одно модальное окно. Что, если бы у нас было несколько других модальных окон? Хотели бы мы управлять модальным состоянием каждый раз, когда оно нам нужно, непосредственно в компонентах? Возможно нет.

Как только мы напишем первый редуктор и подключим его к остальной части приложения, реализация новых редукторов будет довольно простой. Нам просто нужно импортировать их в наш index.js файл и объединить их при создании магазина.

В завершение я хотел бы поделиться реальным редуктором, который я давно реализовал в одном из своих проектов. Это именно то, что мы обсуждали в этой статье:

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

На сегодня все, ребята. Я надеюсь, что эта статья вам чем-то помогла.

Будьте осторожны и удачного кодирования!

Исходный код доступен на GitHub.