useWindowEvent
Описание
useWindowEvent — хук для типобезопасного подключения нативных событий глобального объекта window. Поддерживает две формы: одиночное событие и карта событий. Хук использует актуальные обработчики без перевешивания слушателей и корректно снимает их при размонтировании. Опции по умолчанию: capture: false, once: false, passive: false.
Сигнатура
ts
// 1) Одиночное событие
function useWindowEvent<T extends UseWindowEventType>(
eventType: T,
eventHandler: UseWindowEventHandler<T>,
eventOptions?: AddEventListenerOptions,
): void;
// 2) Карта событий
function useWindowEvent(eventsMap: UseWindowEventMap): void;Параметры
eventType— строка события окна ('resize','scroll','keydown', и т.д.).eventHandler— обработчик; тип события выводится автоматически.eventOptions?— опции слушателя (capture,once,passive).eventsMap— объект вида{ type: handler | [handler, options] }.
Возвращает
void.
Примеры
1) Логирование ширины окна при resize
tsx
import { useState } from 'react';
import { useWindowEvent } from '@webeach/react-hooks';
export function ViewportWidth() {
const [width, setWidth] = useState(() => window.innerWidth);
useWindowEvent('resize', () => {
setWidth(window.innerWidth);
});
return <div>width: {width}px</div>;
}2) Предупреждение перед уходом со страницы (beforeunload)
tsx
import { useWindowEvent } from '@webeach/react-hooks';
type ConfirmLeaveProps = {
enabled: boolean;
};
export function ConfirmLeave(props: ConfirmLeaveProps) {
const { enabled } = props;
useWindowEvent('beforeunload', (event) => {
if (!enabled) {
return;
}
event.preventDefault();
event.returnValue = '';
});
return null;
}3) Карта событий: scroll (passive) + keydown (once)
tsx
import { useWindowEvent } from '@webeach/react-hooks';
export function ScrollAndHotkey() {
useWindowEvent({
scroll: [
() => {
// работаем без preventDefault; passive=true улучшает производительность скролла
console.debug('scrollY =', window.scrollY);
},
{ passive: true },
],
keydown: [
(event) => {
if (event.key === 'h') {
console.log('hotkey!');
}
},
{ once: true },
],
});
return null;
}Поведение
Подключение в layout‑фазе
- Подписка и отписка выполняются синхронно в layout‑фазе, чтобы не пропускать ранние события до пейнта.
Актуальность обработчиков
- Хук хранит обработчики в «живой» ссылке, поэтому вы можете менять функции между рендерами без перевешивания слушателей — вызовется актуальная версия.
Когда происходит перевешивание
- Слушатели перевешиваются при изменении структуры карты событий/их опций (
capture/once/passive). Изменение самих функций‑обработчиков не требует перевешивания.
- Слушатели перевешиваются при изменении структуры карты событий/их опций (
Опции по умолчанию
- Если опции не указаны, используются
capture: false,once: false,passive: false.
- Если опции не указаны, используются
Автоматическая очистка
- Все подписки автоматически снимаются при размонтировании компонента.
SSR‑безопасность
- Во время рендера к
windowобращений нет; подписка происходит только после маунта.
- Во время рендера к
Когда использовать
- События глобального окна:
resize,scroll,keydown,visibilitychange,beforeunloadи др. - Сценарии, где обработчик часто меняется и важно не перевешивать слушатели.
- Когда удобно описать несколько событий одной картой.
Когда не использовать
- Если хватает React‑обработчиков на элементах (
onClick,onChange) — они не требуют глобальных слушателей. - Для специфичных источников событий (
document,media,BroadcastChannel) используйте соответствующие хуки/обёртки.
Частые ошибки
Отсутствие
passiveдля скролла- Если не планируете вызывать
preventDefault, указывайте{ passive: true }для лучшей производительности прокрутки.
- Если не планируете вызывать
Ожидание синтетических событий React
- Хук работает с нативными событиями
window. Типы и поведение отличаются отSyntheticEvent.
- Хук работает с нативными событиями
Случайная смена опций
- Изменение
capture/once/passiveприводит к перевешиванию. Убедитесь, что это осознанное действие.
- Изменение
Использование
signal- Параметр
signalне поддерживается; используйте собственные механизмы отмены при необходимости.
- Параметр
Типизация
Экспортируемые типы
UseWindowEventHandler<EventType>(event: UseWindowEventInstance<EventType>) => void— типобезопасный обработчик; тип события выводится из имени ('keydown'→KeyboardEvent,'resize'→UIEvent/Event).
UseWindowEventInstance<EventType>- Соответствующий объект события из
WindowEventMap[EventType].
- Соответствующий объект события из
UseWindowEventMap- Сопоставление
{ [type]: handler | [handler, options] }для навешивания нескольких подписок одним вызовом.
- Сопоставление
UseWindowEventOptions- Опции слушателя без
signal:{ capture?: boolean; once?: boolean; passive?: boolean }.
- Опции слушателя без
UseWindowEventType- Объединение всех ключей
WindowEventMap.
- Объединение всех ключей