1.5 KiB
1.5 KiB
title, impact, impactDescription, tags
| title | impact | impactDescription | tags |
|---|---|---|---|
| Store Event Handlers in Refs | LOW | 稳定的订阅 | advanced, hooks, refs, event-handlers, optimization |
将事件处理函数存储在 Refs 中
当回调函数被用于那些不应因回调变化而重新订阅的 effect 时,应将回调存储在 ref 中。
错误做法(每次渲染都重新订阅):
function useWindowEvent(event: string, handler: (e) => void) {
useEffect(() => {
window.addEventListener(event, handler)
return () => window.removeEventListener(event, handler)
}, [event, handler])
}
正确做法(稳定的订阅):
function useWindowEvent(event: string, handler: (e) => void) {
const handlerRef = useRef(handler)
useEffect(() => {
handlerRef.current = handler
}, [handler])
useEffect(() => {
const listener = (e) => handlerRef.current(e)
window.addEventListener(event, listener)
return () => window.removeEventListener(event, listener)
}, [event])
}
替代方案:如果你在使用最新版 React,可以使用 useEffectEvent:
import { useEffectEvent } from 'react'
function useWindowEvent(event: string, handler: (e) => void) {
const onEvent = useEffectEvent(handler)
useEffect(() => {
window.addEventListener(event, onEvent)
return () => window.removeEventListener(event, onEvent)
}, [event])
}
useEffectEvent 为同一模式提供了更简洁的 API:它创建一个稳定的函数引用,始终调用最新版本的处理函数。