Прокачиваем навыки React с помощью слушателей событий

Прокачиваем навыки React с помощью слушателей событий

Фото Ника Фьюингса на UnsplashФото Ника Фьюингса на Unsplash

Если вы участвовали в проектах на JavaScript в качестве фронтенд/бекенд разработчика, то вы должны быть хорошо знакомы с прикреплением событий к документу, элементу или объекту окна через встроенный модуль событий.

React создает уровень абстракции над основным модулем JavaScript, чтобы предоставить оболочку событий (Synthetic Event wrapper), с помощью которой можно получить доступ к элементам Virtual DOM и манипулировать ими. В большинстве случаев это все, что нужно для передачи функции одному из Synthetic Event обработчиков.

Статья поможет понять:

  • как правильно добавлять, очищать и отслеживать слушателей событий;
  • как строить стратегии производительности и оптимизации слушателей;
  • зачем необходимо создавать пользовательские event listener;
  • для чего использовать традиционные и “реактивные” реализации.

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

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

Вот как это делается в функциональном компоненте:

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

Еще один способ убедиться, что слушатели находятся в нужных местах или успешно удалены – проверять их и контролировать. Сделать это можно в Chrome Dev Tools :

Прокачиваем навыки React с помощью слушателей событий

Когда мы открываем инструменты разработчика и переходим к некоему элементу (в нашем случае – к документу) можно видеть, что EventListener прикреплен к DOM, ожидая выполнения.

Поскольку в статье используется codesandbox , можно заметить дополнительных слушателей в списке ниже. Так все выглядело бы во вкладке Event Listeners при наличии нескольких слушателей на объектах window, document и element:

Подключено несколько слушателейПодключено несколько слушателей

Если внимательно посмотреть на последний скриншот, можно увидеть события “ contextmenu ” и “ auxclick ”, добавленные из codesandbox в глобальное пространство имен событий.

Еще раз подчеркнем, что во избежание каких-либо проблем со слушателями событий нужно правильно добавлять (на этапе монтажа компонента) и очищать их.

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

В методе addEventListener есть третий аргумент, позволяющий указывать дополнительные параметры, такие, как свойство once:

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

Еще один очень удобный флаг – passive option. С его помощью можно значительно улучшить производительность listener и сократить время отклика элементов. Вот как это выглядит:

Логическое значение true сообщает, что указанная слушателем функция никогда не вызовет функцию preventDefault () . Если пассивный слушатель вызывает функцию preventDefault (), агент пользователя создаст предупреждение в консоли. Дополнительные сведения для изучения ключей можно найти в разделе улучшение производительности .

В качестве эксперимента автор проверяет производительность слушателя с опцией и без. При обычном слушателе время выполнения составляет примерно 164мс, а с passive option, время выполнения упало до 116мс – на 30% эффективнее.

React предоставляет нам набор событий, но иногда может понадобиться более гибкое решение: обработать сложную анимацию, пользовательское скролл-событие, вызывающее изменения UI, или попытаться избежать перекрытия событий click в глобальном пространстве имен.

Мы всегда можем создать собственные события:

Разберем , что здесь происходит .

  • Мы ожидаем, что в метод createCustomEvent будут переданы два параметра: имя события и любые дополнительные данные, находящиеся в параметре detail.
  • Внутри тела метода мы проверяем, существует ли объект window. Если нет, событие не может быть присоединено, и мы вернем null. В ином случае вернем конструктор CustomEvent, создающий пользовательское событие и передающий любые данные внутрь объекта detail.

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

Теперь рассмотрим эту часть кода:

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

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

Использование слушателей событий в React – не то, чем можно регулярно злоупотреблять. Лучше использовать предоставляемый React по умолчанию Synthetic Event.

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