React useEffect依赖数组传ref与ref.current有什么区别
React中useEffect依赖ref与ref.current的差异
首先明确基础前提:useRef()返回的ref对象,在组件整个生命周期内的引用是固定不变的——React会保证每次组件渲染拿到的都是同一个内存对象,只有对象上的.current属性可以被手动修改。
第一种写法:依赖为[renderRefs.current]
触发逻辑
React会在每次组件重渲染时,对当前渲染周期读到的renderRefs.current值和上一次渲染缓存的旧值做浅比较,只有二者不相等的时候才会触发effect执行。
执行时机特点
- 仅当组件发生重渲染、且重渲染时
renderRefs.current的值和上次不一致,effect才会执行。 - 存在明显的响应盲区:如果你是在事件回调、定时器、DOM原生事件监听这类不会自动触发React重渲染的逻辑里修改
renderRefs.current,修改完成后React不会主动跑依赖校验,effect完全不会触发。 - 常见场景:如果用ref存DOM节点引用,初始
renderRefs.current是undefined,组件挂载完成后React会触发一次重渲染,此时current变成真实DOM节点,和初始值不一致,effect会触发一次;但后续你手动修改current存储其他值时,如果修改操作没有触发组件重渲染,effect不会有任何响应。
第二种写法:依赖为[renderRefs]
触发逻辑
React对比的是renderRefs这个对象本身的引用,而前面已经说过,useRef返回的对象引用终身不变,所以依赖对比永远返回「无变化」。
执行时机特点
- 这个effect只会在组件首次挂载完成后执行1次,后续不管组件重渲染多少次、不管你怎么修改
renderRefs.current的值,effect永远不会重新执行。 - 实际运行效果和写空依赖
useEffect(() => {}, [])完全一致,唯一区别是不会触发react-hooks/exhaustive-deps规则的依赖缺失警告。
核心差异总结
- 依赖
renderRefs.current:effect触发和重渲染行为强绑定,只能响应「触发了重渲染的current值变化」,无法响应不触发重渲染的current修改,稳定性差。 - 依赖
renderRefs:effect仅在挂载时执行一次,完全不会响应current的任何变化,和空依赖效果等价。
注意:React官方不推荐将
ref.current作为useEffect的依赖项,因为ref是可变的,它的属性变化不会自动触发组件更新,很容易出现effect不按预期触发的问题。如果需要让值的变化能被useEffect正确捕获,应该优先使用useState管理状态。
内容的提问来源于stack exchange,提问作者Flezcano
相关产品推荐
相关产品推荐

