React中此处useRef是否冗余?能否用普通变量替代useRef包裹的order数组
useRef存储顺序数组的设计目的与替换可行性分析
原代码使用useRef的设计目的
这段代码服务于拖拽类交互的顺序索引存储逻辑,使用useRef的核心设计目标是借助它的两个原生特性匹配业务需求:
- 引用稳定性:返回的ref对象在组件整个生命周期内保持固定的内存引用,不会因为组件重渲染被销毁重建
- 可变操作不触发渲染:直接修改ref.current的属性值,不会触发React的组件重渲染流程
对应到具体交互场景:
- 拖拽过程中会高频调整顺序索引值,将这个可变数据存在ref中,就不会因为每次微小的顺序调整触发整棵组件树的重渲染,仅在拖拽操作完成需要同步视觉反馈时手动触发状态更新即可,大幅降低交互阶段的性能开销
- 组件后续因为props变化、其他状态更新触发重渲染时,不会重新执行数组生成逻辑覆盖已经调整好的自定义顺序,保证拖拽调整的排列效果不会被意外重置
能否替换为普通变量声明
结论是不可以直接替换,会导致明确的功能bug,两者的运行逻辑存在本质差异:
- 普通变量不具备生命周期持久能力
组件函数体中通过var/const声明的普通变量,会在每一次组件重渲染时被重新执行初始化逻辑。也就是说只要组件因为任何原因重新渲染(比如父组件传入新的props、其他绑定的state发生变化),都会重新执行一次items.map生成全新的初始索引数组,直接将之前拖拽调整好的顺序重置回默认排列,交互效果会完全丢失。
而useRef的初始化逻辑(也就是传入的items.map参数)只会在组件首次挂载时执行一次,后续重渲染过程中React会忽略这个传入的参数,直接返回之前缓存的ref对象。 - 普通变量无法解决闭包旧值问题
拖拽逻辑通常会绑定DOM原生事件的回调函数,这些回调往往是在组件首次挂载时生成的闭包。如果order是普通的函数体内变量,重渲染后生成的新数组引用不会被旧闭包捕获,回调里拿到的order值永远是首次渲染时的初始顺序,后续的拖拽调整永远不会被回调逻辑读到。
而useRef返回的对象是稳定引用,哪怕重渲染了很多次,旧闭包里拿到的ref对象始终能通过ref.current访问到最新修改的顺序值,不存在捕获旧值的问题。
补充说明:很多开发者对useRef的认知停留在“用来获取DOM节点”,实际上它的原生设计定位就是“组件实例级的可变存储空间”,获取DOM节点只是这个能力的衍生应用场景。如果确实需要简化代码不写
.current,可以通过自定义Hook封装访问逻辑,但绝对不能直接替换成函数体里的普通变量。
内容的提问来源于stack exchange,提问作者ZenBerry
相关产品推荐
相关产品推荐

