React useRef Hook内部机制及跨渲染值保持不变的原因解析
关于React useRef Hook的工作原理与跨渲染值保持的疑问解答
1. useRef Hook的内部工作原理
useRef是React提供的用于创建可变引用对象的Hook,核心逻辑如下:
- 组件首次渲染时,调用
useRef(initialValue)会创建一个新的引用对象,将传入的initialValue赋值给该对象的.current属性,随后把这个对象返回给组件。 - 组件后续重渲染时,再次调用
useRef(initialValue)不会创建新的引用对象,而是直接返回首次渲染时创建的那个对象——此时传入的initialValue会被React忽略,不会覆盖已有值。
2. useRef如何确保值在跨渲染时不变
React会为每个组件实例维护一个Hook状态队列,每个Hook的调用顺序是固定的:
- 首次渲染时,useRef会在这个队列中注册一个条目,存储创建的引用对象。
- 后续重渲染时,React会严格按照Hook的调用顺序,从队列中取出对应的引用对象返回给组件。
- 这个引用对象的生命周期和组件实例绑定,不会随渲染周期销毁或重建,因此它的
.current属性值能在多次渲染之间保持稳定,除非你主动修改它。
针对你的代码场景的具体解释
你代码中const roomBasePrice1 = useRef(roomPricePreDiscount)这一行:
- 组件首次渲染时,
roomPricePreDiscount的初始值50会被赋值给roomBasePrice1.current。 - 当你点击按钮调用
setRoomPricePreDiscount更新状态引发重渲染后,虽然代码会再次执行到这一行,但React不会用新的roomPricePreDiscount值去更新roomBasePrice1.current——因为useRef的初始值参数仅在首次渲染时生效。
而如果直接写const roomBasePrice1 = roomPricePreDiscount,这只是普通的JavaScript变量声明,每次组件函数执行(重渲染)时,都会重新将当前的roomPricePreDiscount值赋值给它,这就是你不想要的结果。
如果需要验证,你可以在组件内添加日志:
console.log(roomBasePrice1.current);
首次渲染会输出50,后续更新roomPricePreDiscount后,日志依然会输出50,除非你主动执行roomBasePrice1.current = 新值来修改它。
内容的提问来源于stack exchange,提问作者user20273569
相关产品推荐
相关产品推荐

