You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在useEffect回调中获取最新状态:自制useEvent替代钩子是否合理?

useEffect回调读取最新状态/属性的替代方案探讨

背景

useEvent 可以解决在 useEffect 内部回调中读取最新 props/state 的问题,但截至2022年11月仍无法用于生产环境,其使用场景在React Beta版文档中有记载。

问题场景

const SomeComponent = ({ prop1, ...}) => {
  const [state, setState] = useState('initial')

  useEffect(() => {
    // 希望在connect回调中获取最新的state和props,同时不想因state变化重连
    // 这里的事件处理器依赖prop1和state
    const connection = createConnection(...)
    connection.on('connect', () => {
      // 需要引用prop1和state的最新值
      // 如果不把这些变量加入依赖数组,effect无法获取最新值
    })

    return () => {
      connection.disconnect()
    }
  }, []) 

上述代码中,若将prop1和state加入useEffect的依赖数组,会触发不必要的重连;但不加入的话,回调又无法获取最新的变量值。

基于useRef的临时解决方案

const SomeComponent = ({ prop1, ...}) => {
  const [state, setState] = useState()

  const someFunction = () => {
    // 使用最新的prop1和state
  }

  const someFunctionRef = useRef()
  someFunctionRef.current = someFunction;

  useEffect(() => {
    const someFunctionRefWrapper = () => {
      someFunctionRef.current()
    }

    // 需要读取最新的props/state,但不想因这些值变化触发重渲染
    const connection = createConnection(...)
    connection.on('connect', someFunctionRefWrapper)

    return () => {
      connection.disconnect()
    }
  }, [])

自定义替代钩子

由于useEvent无法用于生产环境,编写了如下自定义钩子:

const usePoorMansUseEvent = (callback) => {
  const itemRef = useRef();
  itemRef.current = callback;

  const stableReference = useCallback((...args) => {
    itemRef.current(...args)
  }, []);

  return stableReference;
}

问题解答

是不是在重复造轮子?

没错,你写的这个钩子本质就是useEvent的核心实现——用useRef实时保存最新的回调,再通过useCallback返回一个引用稳定的包装函数,调用时始终执行最新的回调逻辑。从功能上看,和官方useEvent的临时替代思路完全一致。

有没有更优的解决方案?

在useEvent正式发布并可用于生产前,这个方案已经是社区公认的最佳临时替代方案之一,没有太多更优的选择。不过可以注意几个细节:

  • 确保回调函数本身不会捕获过时变量(你的写法已经通过ref规避了这个问题);
  • 如果回调包含异步逻辑,要注意itemRef.current可能在异步执行过程中被更新的情况,不过大部分场景下这个问题影响有限;
  • 部分第三方工具库也提供了类似能力,但核心逻辑和你写的钩子没有区别,没必要额外引入依赖增加项目复杂度。

内容的提问来源于stack exchange,提问作者Azzy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 15:55:33