[ PROMPT_NODE_25176 ]
advanced-event-handler-refs
[ SKILL_DOCUMENTATION ]
## 在 Refs 中存储事件处理器
当在不应因回调更改而重新订阅的 Effect 中使用回调时,请将回调存储在 refs 中。
**错误示例(每次渲染都会重新订阅):**
tsx
function useWindowEvent(event: string, handler: () => void) {
useEffect(() => {
window.addEventListener(event, handler)
return () => window.removeEventListener(event, handler)
}, [event, handler])
}
**正确示例(稳定的订阅):**
tsx
function useWindowEvent(event: string, handler: () => void) {
const handlerRef = useRef(handler)
useEffect(() => {
handlerRef.current = handler
}, [handler])
useEffect(() => {
const listener = () => handlerRef.current()
window.addEventListener(event, listener)
return () => window.removeEventListener(event, listener)
}, [event])
}
**替代方案:如果您使用的是最新版 React,请使用 `useEffectEvent`:**
tsx
import { useEffectEvent } from 'react'
function useWindowEvent(event: string, handler: () => void) {
const onEvent = useEffectEvent(handler)
useEffect(() => {
window.addEventListener(event, onEvent)
return () => window.removeEventListener(event, onEvent)
}, [event])
}
`useEffectEvent` 为相同的模式提供了更简洁的 API:它创建了一个稳定的函数引用,该引用始终调用最新版本的处理器。