Как сделать модальное окно react

Добавил пользователь Евгений Кузнецов
Обновлено: 05.10.2024

Что делать, если скорость разработки уже не та, что раньше? Отказавшись от монолита, изменить подход к написанию кода и начать использовать его повторно!

☕ Пиши на React в два раза быстрее! Простые трюки для крутого разработчика

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

Вам помогут переиспользуемые блоки кода! Переиспользуемые блоки кода – то, что нужно прогрессивному разработчику!

Так бросим же все силы на то, чтобы научиться мыслить в компонентном стиле!

Учимся готовить компоненты

Казалось бы, каждый джун сегодня умеет писать компоненты, чему тут учиться? Но компонент компоненту рознь, для наших программ нужны только самые качественные и красивые из них. Поэтому сейчас мы возьмем неограненный React-компонент, который написал простой разработчик вроде вас, и рассмотрим его очень пристально со всех сторон. А затем много-много раз отрефакторим, пока не получится идеальный бриллиант.

Будьте готовы к многочисленным озарениям и головокружительному увеличению вашей производительности!

Исходный компонент

Рассмотрим неограненный алмаз, с которым мы будем работать. Этот простой компонент умеет не так уж и много:

  1. он получает с бэкенда список браузеров;
  2. отображает индикатор загрузки, пока запрос выполняется;
  3. выводит полученные данные в виде карточек;
  4. если пользователь нажимает на карточку, компонент показывает модальное окно с детальной информацией о браузере.

Этот код похож на ваш?

Что с этим компонентом так?

Что с этим компонентом не так?

К чему мы стремимся?

Чем больше у вас разных кирпичиков, тем быстрее вы можете построить дом.

  • Не нужно повторять одно и то же по десять раз – помним о принципе DRY !
  • Не нужно вносить изменения в нескольких местах – и лихорадочно вспоминать, где еще есть этот функционал.
  • Не нужно ловить баги по всему приложению – они смирно сидят в компоненте и ждут вас.
  • Не нужно много читать, код сразу становится короче, чище и понятнее.
  • Не нужно писать тесты для каждого места, в котором используется функциональность.

Приступаем к огранке

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

Одно элементарное действие – и наш компонент уже может работать с другим URL. Маленький шаг для разработчика, но огромный прыжок для переиспользуемого блока!

Вероятно, это самая важная фундаментальная установка хорошего разработчика – разделение бизнес-логики от логики отображения. Жизнь становится проще, когда UI компоненты ничего не знают о серверах, логике и состоянии приложения .

В чем вообще разница?

Бизнес-логика: Код, который принимает решения и изменяет состояния. Все внутри
до инструкции return .

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

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

  • Пользовательский хук useBrowsers() с бизнес-логикой.
  • Компонент
    с логикой отображения.

Код все еще далек от идеала, но уже стал немного более удобным.

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

☕ Пиши на React в два раза быстрее! Простые трюки для крутого разработчика

  1. index.js экспортирует
    из Browsers.jsx;
  2. строительные блоки для
    лежат в папках components и hooks;

BrowsersList.jsx можно развить до самостоятельной папки с собственными хуками, компонентами и файлом index.js

☕ Пиши на React в два раза быстрее! Простые трюки для крутого разработчика

Посмотрим на BrowsersList.jsx:

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

Большая проблема маленьких файлов

Взгляните на сигнатуру функции
. Что произойдет, если мы переименуем какой-нибудь пропс, например, changeDescription на setSelectedBrowser ? Или удалим аргумент? Или добавим новый?

Все сломается!

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

Посмотрите внимательно, все ли тут в порядке?

Бинго! Одна маленькая опечатка – и все идет кувырком.

Сколько прекрасных часов проводят молодые разработчики, сравнивая пропсы и пытаясь понять, что же сломалось – но мы-то с вами уже не такие! Давайте решать проблему радикально.

Хватит медленно кодить на JS, давайте кодить быстро на TS

В 2021 году у вас нет оправданий, если вы не используете TypeScript. Вам даже не требуется сразу же изучить все его возможности, ведь можно просто добавить TS в проект, не меняя ни строчки , и постепенно наращивать его применение.

38% багов на Airbnb можно было предотвратить с помощью TypeScript

38% багов на Airbnb можно было предотвратить с помощью TypeScript

С TypeScript ваша IDE обогатится несколькими крутыми фичами:

А вот, кстати, и наша опечатка:

☕ Пиши на React в два раза быстрее! Простые трюки для крутого разработчика

Теперь обновим сигнатуру useBrowsers() :

И теперь TypeScript будет строго следить, чтобы useBrowsers() и BrowsersList были совместимы.

Быстрая разработка архитектуры

BrowsersListProps выглядит весьма нагруженно:

  • Одна строчка – для состояния загрузки.
  • Одна строчка – для списка браузеров.
  • Целых четыре строчки – для отображения детальной информации о браузере в модальном окне. Есть большая вероятность, что потребуется выводить больше данных, а значит сигнатура может измениться. А это весьма беспокойное дело, как мы помним.

Мы можем уменьшить сложность этого фрагмента и отрефакторить функциональность модального окна для использования типа Browser :

TypeScript указывает на некорректность сигнатуры при ее изменении

TypeScript указывает на некорректность сигнатуры при ее изменении

Этот маленький рефакторинг должен продемонстрировать вам замечательную способность TypeScript: быстро проектировать системный дизайн. Писать типы очень просто. Они маленькие, но содержат много полезной информации о вашей системе. Фактически вы можете описать вашу программу без кода, одними типами.

Теперь поправим
, чтобы он мог работать с новой сигнатурой BrowsersListProps .

Отрефакторим
. Сейчас он принимает множество пропсов, и это явный сигнал для внесения правок. Теперь он будет принимать всего 2 аргумента:

Компонент стал проще и надежнее.

Если вы немного помедитируете на компонент, то на вас снизойдет просветление. Список с "состоянием загрузки" – это очень крутая и востребованная функциональность, которая наверняка будет использоваться везде, где только можно.

Сейчас эта функциональность интегрирорована в
. Значит надо ее извлечь. Создадим новый компонент и будем использовать его вместо простого .

Как всегда начнем с определения типов:

  • T – это аргумент типа, или дженерик. То же самое, что arg в сигнатуре foo(arg) . Дженерики нужны, если вы хотите создать свой тип из другого типа. Вот здесь есть подробнейшее описание дженериков.
  • & – это символ пересечения множеств (интерсекция). Тип X = A & B означает, что X содержит в себе свойства A и B .

Итак, что мы сделали:

  • Определили тип для пропсов нового компонента.
  • Использовали дженерик, чтобы указать, что список может содержать элементы разных типов.
  • UIFriendlyListProps расширяет встроенные класс FlatListProps из библиотеки React Native и добавляет в него состояние загрузки.

Теперь вынесем новый компонент в отдельный файл UIFriendlyList.jsx:

Обратите внимание, мы добавили еще пустое состояние, чтобы показать юзеру, что список действительно пуст и он может больше не ждать загрузки. Это прекрасное решение с точки зрения UX.

Компонент – это крутой строительный блок, который очень легко переиспользовать в самых разных ситуациях. Добавьте его в свою коллекцию кирпичиков, чтобы стать еще быстрее.

Во что теперь превратился наш
:

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

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

Мы закончили с логикой отображения, пора вернуться к бизнес-логике.

Хук useBrowswers() должен возвращать валидный объект с типом BrowsersListProps:

Приглядимся повнимательнее. Функциональность "обратиться по некоторому URL и сохранить результат запроса, пока отображается индикатор загрузки" кажется весьма полезной, давайте извлечем ее в новый хук useFetch .

Как всегда, сначала типы. Нам нужно, чтобы useFetch сохранял данные из эндпоинта и отображал состояние загрузки. Формат данных будет задан отдельно, для этого используем дженерик:

Таким образом, useFetch можно будет использовать с любыми типами данных.

Теперь сама функция:

Для полноты картины добавили Alert при ошибке запроса.

Теперь окончательно отрефакторим useBrowsers() :

Кажется, здесь больше нечего извлекать :)

4 простых совета для ускорения разработки

1. Никогда не форматируйте код вручную.

Используйте возможности IDE, ESLint и Prettier.

2. Никогда не импортируйте модули вручную

Использование автоматического импорта сэкономит много времени.

3. Научитесь ориентироваться среди множества файлов

Разделяя проект на маленькие переиспользуемые кирпичики вы неизбежно приходите к монструозной файловой структуре вроде этой:

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

4. Используйте линтинг

Это поможет найти самые хитрые и вредные ошибки:

☕ Пиши на React в два раза быстрее! Простые трюки для крутого разработчика

Искусство быстрой разработки

Чтобы быть быстрым, не потеряв при этом в качестве, вам нужно освоить несколько вещей:

  • Отделять бизнес-логику от отображения.
  • Разделять код на маленькие реюзабельные компоненты.
  • Использовать TypeScript и начинать работу с определения типов.
  • Практиковаться в рефакторинге.
  • Использовать плюшки вашей IDE.

Насколько вы постигли дзен быстрой разработки? Признавайтесь, часто рефакторите?

Модальное окно для сайта на чистом CSS и JavaScript

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

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

Изображение модального окна:

Вид модального окна, созданного с помощью JavaScript

Оно состоит из заголовка (хедера), основной части и футера.

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

Загрузка и установка модального окна

Проект модального окна расположен на GitHub. Перейти к нему можно по этой ссылке.

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

Как создать и вызвать модальное окно

Эта реализация модального окна не требует непосредственного размещения его HTML кода на странице . Это выполняется программно.

Таким образом, для того чтобы создать его достаточно просто вызвать функцию $modal :

При создании окна вы можете сразу же его настроить, для этого в данную функцию необходимо передать данные в формате объекта. Осуществляется это с помощью соответствующих ключей (свойств). Например, с помощью ключа title вы можете задать заголовок, который будет иметь всплывающее окно по умолчанию. Ключ content позволяет установить содержимое, а footerButtons – кнопки для отображения их в его нижней части (футере).

Ключ footerButtons в отличие от title и content принимает в качестве значения массив объектов . Каждый объект в этом массиве представляет собой кнопку . Она задаётся с помощью ключей text , class , handler . С помощью них вы можете установить кнопке (элементу ) текст, значение атрибутов class и data-handler . Если ключ footerButtons вообще не указать, то в этом случае модальное окно будет создано без футера.

Пример создания модального окна с настройками по умолчанию:

Но функция $modal не только создаёт модальное окно в DOM, но также предоставляет методы для управления им.

Для этого нужно создать переменную и присвоить ей результат выполнения функции $modal .

В эту созданную переменную будет помещён объект (а точнее ссылка на него), имеющий следующие методы:

  • show – для отображения модального окна;
  • hide – для скрытия модального окна;
  • destroy – для удаления модального окна из DOM и связанных с ним обработчиков событий;
  • setContent – для установки контента;
  • setTitle – для установки заголовка.

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

Рассмотрим, как работать с этими методами на примерах.

Например, метод show используется когда вам необходимо показать (открыть) модальное окно:

Метод hide применяется для его скрытия:

Методы setContent и setTitle предназначены соответственно для изменения контента и заголовка модального окна после его создания.

В возвращаемом объекте также есть метод destroy . Его необходимо использовать только когда вам необходимо полностью удалить модальное окно из DOM, а также связанные с ним события:

Данную операцию имеет смысл использовать только в том случае, если созданное модальное окно вам больше не нужно на странице.

Примеры использования скрипта для создания модальных окон

1. Пример кода, выполняющий открытие модального окна при нажатии на определённую кнопку.

2. Пример кода, позволяющий открыть одно и тоже модальное окно посредством клика на разные элементы (определяется элемент, который может открыть это окно, с помощью наличия у него атрибута data-toggle="modal" ):

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

5. Пример, в котором создано 2 разных модальных окна. Первое модальное окно открывается при нажатии на одни элементы, а второе – при клике на другие:

6. Пример всплывающего окна, данные в которое загружаются с использованием AJAX:

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

Описание скрипта модального окна

В этом разделе приведена информация для тех, кто хочет более подробно разобраться с тем, как работает это модальное окно.

Её JavaScript код представлен посредством функции $modal :

В качестве результата эта функция возвращает объект, состоящий из 5 методов. Они позволяют нам выполнять различные действия над созданным модальным окном. Назначение каждого метода, а также различные примеры как их использовать мы уже подробно рассмотрели выше. Здесь мы более подробно разберём внутренние переменные и функции $modal .

В $modal имеются следующие переменные _elemModal , _eventShowModal , _eventHideModal , _hiding , _destroyed , _animationSpeed и функции _createModal , _showModal , _hideModal , _handlerCloseModal .

Функция _createModal предназначена для формирования HTML-кода модального окна (DOM структуры) и добавления её на страницу. В качестве результата она возвращает ссылку на базовый элемент этого модального окна. Т.к. нам эта ссылка нужна в других частях $modal , то сохраним её в переменную _elemModal :

Переменные _hiding и _destroyed используются для хранения состояний. Первая применяется для индикации процесса скрытия модального окна. Она имеет значение true во время скрытия окна, в остальных моментах - false . Вторая переменная хранит true или false , в зависимости от того, удалены ли DOM элементы модального окна со страницы и связанные с ним события или нет.

Переменная _animationSpeed используется для указания времени длительности процесса скрытия модального окна (в миллисекундах).

Функция _showModal предназначена для включения отображения модального окна на странице, а _hideModal – для его скрытия.


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

Стили с комментариями для модальных окон

Пишем логику на JavaScript

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

Код с комментариями

Получаем следующий результат

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quis ex, modi. Eos modi eum debitis vero impedit delectus cumque rem velit laboriosam sunt beatae odit, a cupiditate quae sit voluptatum.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Veniam, iure, corporis eum beatae ut deleniti aperiam placeat maxime, eveniet non error. Fugiat placeat sit voluptatibus cumque quis adipisci porro quod eligendi maxime nemo impedit omnis, deserunt, esse sequi quos ullam, eos voluptatem ipsa iure animi. Error soluta laborum excepturi fugiat ratione eum, provident omnis deleniti illum animi placeat ea esse sunt atque, exercitationem eveniet sed consectetur quia quod vitae nemo velit. Officiis, possimus quia fugit aut maiores ad dignissimos rerum mollitia vitae voluptates. Quae cum inventore voluptate voluptatem debitis harum dignissimos accusamus dolorem cumque atque quam, repudiandae nam, quasi, ipsam deserunt. Voluptatem doloribus repudiandae voluptatum asperiores, impedit culpa, excepturi maxime libero architecto repellat enim velit quasi, facere iusto magni fugiat, iste provident ducimus maiores. Quos dolorum, eveniet nihil blanditiis, sint placeat, velit dolor, iusto voluptatibus deleniti magni perspiciatis? Consequuntur nesciunt cupiditate, veritatis aliquam sed molestias maiores. Dolorem temporibus, deleniti ex ut quis asperiores, perspiciatis a, nemo placeat dicta possimus aperiam.

Итоги

Опять же, данная реализация не претендует на эталонность. Вы можете использовать данные модальные окна, как один из доступных вариантов. А также, поняв логику, можете написать свой вариант модальных окон, на основе данной реализации

9 простых правил, которые помогут вам создать более удачный дизайн модальных окон

Jul 12, 2021 · 5 min read


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

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

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


Модальное окно в формате “Загрузка…” является довольно распространённой практикой для уведомления о длительных операциях. Использование модальных окон в таких случаях можно считать логичным, поскольку такое окно не позволяет пользователю взаимодействовать с экраном. Однако можно найти и более подходящее решение — добавление на сайт строки загрузки прямо в кнопку, которая начинает действие. Такое решение будет сигнализировать о том, что нужно немного подождать, и не дает пользователю снова нажать на кнопку загрузки.

Уведомление об успешном выполнении всегда лучше выводить либо прямо внутри интерфейса, либо на отдельной странице.

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


2. Осторожнее с модальными окнами, вызываемыми системой

Есть два типа модальных окон: вызываемые пользователем и вызываемые системой:

  • Те, что вызваны пользователем, появляются на экране лишь тогда, когда человек сам этого хочет (например, нажимает на кнопку). В этом случае пользователь понимает, почему появляется окно.
  • Те окна, вызываемые системой, которые лишь прерывают задачу, выполняемую человеком. Одна из самых больших проблем с таким типом модальности заключается в том, что эти окна отвлекают пользователей от того, что они делали до появления окна. Человек может даже не понять, почему оно всплыло.

Дизайнеры обычно используют такие окна в рекламных целях. Такие окна прерывают пользователя и заставляют его выполнить какое-либо определенное действие. “Незваные” окна часто производят плохое впечатление на пользователей — люди инстинктивно ищут кнопку “закрыть”. Такие окна считаются раздражающими и неуместными.


3. Убедитесь, что пользователи понимают, что от них требуется

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

К примеру, если пользователь хочет удалить свои файлы, то вместо того, чтобы спрашивать “Очистить хранилище?” с ответами “Да” или “Нет”, лучше спросить “Вы точно хотите удалить свои файлы?” с вариантами “Удалить” и “Отмена”.

4. Выносите содержимое сайта и его активные кнопки в модальные окна

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

  • В идеале, модальное окно должно содержать пару-тройку предложений, а также не более двух кнопок действия.
  • Третье действие, например кнопка “Узнать больше”, лишь уводит пользователя от основного окна и не дает ему завершить желаемое действие.

5. Делайте кнопки закрытия окна видимыми

Пользователи должны иметь возможность закрыть модальное окно, когда им вздумается. Вот несколько способов, как этого добиться:

  • Добавить заметную кнопку “Закрыть” или “×” в правом верхнем углу окна.
  • Добавить заметную кнопку “Закрыть” или “Отменить” в нижней части окна.
  • Добавить возможность закрытия модального окна при клике за его пределами.

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

7. Выделяйте модальные окна

Вот как можно дать пользователям понять, что перед ними модальное окно:

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

8. Сделайте содержимое модального окна доступным для пользователей с клавиатурой (для ПК)

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

Сделайте так, чтобы пользователь мог закрыть окно по нажатию Esc. Когда пользователи случайно открывают модальное окно, многие из них инстинктивно нажимают клавишу Esc, чтобы вернуться на предыдущую страницу.

9. Не используйте вложенные модальные окна

Никогда не создавайте модальные окна, которые могут вызывать новые модальные окна. Такой подход создает визуальный бардак в дизайне сайта.

Читайте также: