Files
2026-07-13 21:36:17 +08:00

1.5 KiB
Raw Permalink Blame History

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:它创建一个稳定的函数引用,始终调用最新版本的处理函数。