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

使用use-callback-ref的useCallbackRef时,依赖其.current的useEffect为何触发两次

原因分析

这个现象是use-callback-ref的内部实现逻辑和React的useEffect依赖检测规则共同导致的,具体执行流程如下:

  1. 原生React的ref更新不会触发组件重渲染,因此把ref.current放在useEffect依赖里时,只有组件首次渲染会执行一次useEffect,后续current变更不会触发。而useCallbackRef为了实现「ref变更时触发自定义回调」的能力,内部会通过状态更新驱动组件重渲染,保证回调逻辑能正常执行。
  2. 组件首次渲染时,divCbRef.current初始值为null,此时useEffect执行会被你的非空判断拦截,不会触发计数,和你观测到的「null阶段不触发」的现象一致。
  3. DOM挂载完成后,React首先给divCbRef.current赋值为真实DOM节点,随后useCallbackRef触发你传入的自定义回调(setUseCbRefCounter逻辑),触发组件第一次重渲染。
  4. 第一次重渲染完成后,React对比useEffect依赖,发现divCbRef.current从null变成了DOM节点,第一次执行内部计数逻辑,useCbRefEffectCounter变为1。
  5. 为了兼容React并发渲染特性,useCallbackRef会在重渲染后再做一次ref值同步操作,这个操作会被React的依赖检测判定为divCbRef.current发生了变更,因此会第二次执行useEffect,useCbRefEffectCounter变为2,最终呈现出触发两次的现象。

解决方案

有两种方案可以规避这个问题:

  • 优先使用useCallbackRef的第二个参数回调处理ref挂载后的逻辑,这个回调只会在ref真实变更时触发一次,完全符合预期。
  • 如果一定要用useEffect实现相关逻辑,可以把useCbRefCounter作为useEffect的依赖,这个状态只会在ref挂载时变更一次,不会出现重复触发的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 12:09:03