С Redux и хуками
Когда я начал работать с React, одним из моих первых заданий было создание модального диалогового окна для отображения в нем некоторых данных. Я потратил много времени на поиски в Google, как создать функцию, которую я мог бы вызвать для отображения какого-нибудь окна. Для меня это было естественным поступком. Даже VanillaJs позволяет вам просто вызвать функцию alert
для отображения простого диалогового окна. Я не мог понять, почему в React все по-другому.
Но, как видите, React работает не так. Одна из основных концепций React заключается в том, что если у вас есть состояние, и оно не меняется, вы можете отображать страницу столько раз, сколько захотите, и она всегда будет выглядеть одинаково. Но вызов функции, которая будет отображать модальное окно, противоречит этому принципу. Модальное окно будет отображаться не в зависимости от состояния компонента, а в зависимости от вызова какой-либо функции.
Так как же нам это сделать?
Во-первых, давайте создадим компонент, который должен открывать модальное окно. У нас будет простой компонент с кнопкой, и при нажатии на кнопку мы захотим, чтобы открывалось окно подтверждения. На консоли появится сообщение "Давай сделаем это!" если confirm
принят, и ничего не будет делать, если confirm
будет отменен.
Довольно просто, правда? Но теперь давайте создадим собственный confirm
модальный файл и избавимся от встроенного confirm
. Что мы сделаем, так это добавим состояние к компоненту, добавим флаг с именем openConfirm
и отрендерим наш собственный компонент на основе этого. Затем мы предоставим метод, который должен вызываться при подтверждении в качестве опоры для нашего модального компонента.
Мы также должны создать наш CustomConfirm
компонент с некоторым индивидуальным стилем и правильной привязкой реквизита к кнопкам:
Вуаля, готово! Вот как вы создаете простые модальные окна в стиле React.
Но прежде чем мы начнем праздновать, давайте рассмотрим более сложную ситуацию. В нескольких проектах мне приходилось открывать разные модальные окна из разных частей приложений с некоторой загрузкой данных API для отдыха. Как вы, наверное, знаете, если вы хотите изменить состояние компонента из разных частей приложения в React, вы будете использовать глобальный поставщик состояния, такой как Flux или Redux. Чего вы, вероятно, не хотите, так это иметь отдельный редуктор для каждого модального окна, особенно если их у вас много.
Вот почему я создал общий модальный компонент, который отображает все разные модальные окна, заботясь об управлении состоянием Redux и открытии / закрытии модального окна. Давайте посмотрим, как вы можете сделать то же самое.
Поскольку этот подход будет тесно связан с магазином Redux, давайте начнем с него. Во-первых, нам нужен модальный редуктор, который будет содержать данные о нашем модальном окне и выполнять с ними операции. В общем, нам нужно два типа действий:
- Открыть модальное окно заданного типа с заданными данными.
- Закройте модальное окно.
Это довольно просто реализовать в редукторе:
Этот редуктор выполняет только две вещи: устанавливает данные, если отправлено действие OPEN_MODAL
, или устанавливает состояние в null
, если отправлено действие CLOSE_MODAL
. Чтобы лучше понять, какие данные отправляются на OPEN_MODAL
, давайте посмотрим на действия:
Как видите, мы выполнили асинхронную операцию и получили некоторые данные (в данном случае profile
). Затем мы отправляем действие OPEN_MODAL
с типом модального окна, которое мы хотим отобразить, и любыми данными, которые мы хотим передать туда. Все, что нам нужно сделать сейчас, это использовать эти данные в компоненте, который будет обертывать все наши модальные окна:
Здесь мы связали наши модальные данные из глобального состояния с Modal
компонентом. Мы также предоставляем функцию как опору, которая позволяет отправлять действие closeModal
. Затем мы берем эти данные и визуализируем модальное окно.
<div className="modal"> ... </div>
Это наше модальное окно со всеми необходимыми стилями. В нем у нас есть проверка на modal.type
. Исходя из этого, мы отображаем правильное модальное тело (в нашем случае ProfileModal
). А затем у нас есть кнопка закрытия, которая позволяет нам закрыть окно. Конечно, в реальном приложении вы также можете добавить причудливый заголовок и нижний колонтитул. Все, что осталось сделать, это добавить компонент Modal
к корневому компоненту нашего приложения, чтобы каждый раз, когда открывается какой-нибудь модальный файл, компонент Modal
может отображаться. В моем случае я просто поместил его в App.js
файл:
Как видите, все, что мы здесь сделали, это создали кнопку, которая отправляет действие openProfile
, которое извлекает некоторые данные API, а затем открывает модальное окно.
Вот и все! Мы создали наш общий модальный компонент. Я знаю, что этот подход может показаться слишком сложным, чтобы отображать одно дурацкое модальное окно. Но, делая это таким образом и фактически следуя мышлению React, вы создадите приятные и чистые компоненты, которые легко использовать повторно и которые приятно тестировать.
Вы можете проверить все работающее приложение на GitHub.