Created
October 13, 2020 06:22
-
-
Save anatooly/50763db1fce9ea9d29e8d60ca8ff47d8 to your computer and use it in GitHub Desktop.
useEventListener
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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