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

Перевод публикуется с сокращениями, автор оригинальной статьи Stefan Metodiev.

***

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

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

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

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

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

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

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

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

 React.useEffect(() > { document.addEventListener(‘click’, addIngredientHandler); return ():void > document.removeEventListener(‘click’, addIngredientHandler) }, []) 

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

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

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

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

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

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

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

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

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

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

 React.useEffect(() > { document.addEventListener(‘click’, addIngreientsHandler, { once: true }); }, []) 

once

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

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

 React.useEffect(() > { document.addEventListener(‘click’, addIngreientsHandler, { passive: true });
}, []) 

passive

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

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

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

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

 const createCustomEvent = (eventName: string, additionalData: {[key: string]: string }): CustomEvent | null > { if (window) { return new CustomEvent(eventName, { detail: { additionalData } }); } return null;
}; 

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

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

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

 export const toggleSideDrawerHandler = (additionalData: {[key: string]: string }): void > { const typeOfEvent = createCustomEvent(‘toggleDrawer’, additionalData); document.dispatchEvent(typeOfEvent);
}; 

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

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

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

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

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

Наслаждайтесь и счастливого взлома!

proglib.io

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

Ваш e-mail не будет опубликован.

19 − пятнадцать =