Skip to content

Instantly share code, notes, and snippets.

@anatooly
Created October 13, 2020 06:22
Show Gist options
  • Save anatooly/50763db1fce9ea9d29e8d60ca8ff47d8 to your computer and use it in GitHub Desktop.
Save anatooly/50763db1fce9ea9d29e8d60ca8ff47d8 to your computer and use it in GitHub Desktop.
useEventListener
import { useState, useRef, useEffect, useCallback } from "react";
// использование
function App() {
// состояние для хранения координат курсора
const [coords, setCoords] = useState({ x: 0, y: 0 });
// обработчик событий обернут в useCallback,
// поэтому ссылка никогда не изменится
const handler = useCallback(
({ clientX, clientY }) => {
// обновляем координаты
setCoords({ x: clientX, y: clientY });
},
[setCoords]
);
// добавляем обработчик с помощью нашего хука
useEventListener("mousemove", handler);
return <h1>Позиция курсора: ({(coords.x, coords.y)})</h1>;
}
// хук
function useEventListener(eventName, handler, element = window) {
// создаем ссылку, хранящую обработчик
const saveHandler = useRef();
// обновляем ref.current при изменении обработчика
// это позволяет нашему эффекту всегда иметь дело с последним обработчиком
// без необходимости передавать ему массив зависимостей
// что запускает эффект при каждом рендеринге
useEffect(() => {
saveHandler.current = handler;
}, [handler]);
useEffect(
() => {
// проверяем поддержку addEventListener
const isSupported = element && element.addEventListener;
if (!isSupported) return;
// создаем обработчик событий, который вызывает обработчик, сохраненный в ref
const eventListener = (event) => saveHandler.current(event);
// добавляем обработчик событий
element.addEventListener(eventName, eventListener);
// удаляем обработчик событий на выходе
return () => {
element.removeEventListener(eventName, eventListener);
};
},
[eventName, element] // перезапускаем только при изменении элемента
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment