useRef构建出一个状态,这个状态不受React控制,变化不会造成页面重新渲染,同时也不会因组件重新渲染而初始化
const myRef=useRef()
useRef的主要使用场景
1. 访问DOM节点或React元素。
2. 保存可变值,这些值的变更不需要触发重新渲染,且在组件生命周期内持久化。
使用技巧
- 在函数组件中访问DOM元素时,使用useRef初始化ref,并将其作为ref属性传递给元素。
- 使用useEffect或事件处理函数来访问ref.current,确保组件已挂载。
- 保存定时器ID、事件监听器、之前的state值等不需要渲染的数据。
- 结合forwardRef和useImperativeHandle向父组件暴露子组件的特定方法或DOM节点。
- 在自定义Hook中使用useRef来保存状态,避免不必要的渲染。
需要注意的问题:
- 修改ref.current不会触发重新渲染,所以如果需要根据ref的值更新UI,应结合状态使用。
- 在条件或循环中使用useRef时,应遵循Hooks的规则,确保每次渲染时Hooks的调用顺序一致。
- 及时清理ref中保存的资源(如定时器、监听器),避免内存泄漏。
访问 DOM 元素
const inputRef = useRef(null);
<input ref={inputRef} />
useEffect(() => {
inputRef.current.focus(); // 自动聚焦输入框
}, []);
保存可变数据
//存储定时器 ID、缓存数据等,修改 .current 不会触发重新渲染
const timerRef = useRef(null);
useEffect(() => {
timerRef.current = setInterval(() => {}, 1000);
return () => clearInterval(timerRef.current); // 清理定时器
}, []);
通过 forwardRef使用
const Child = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
}));
return <input ref={inputRef} />;
});
总结场景
-
DOM 操作:聚焦、滚动、测量元素尺寸。
-
数据持久化:跨渲染保存数据,如定时器、动画帧 ID、历史值。
-
子组件通信:通过
forwardRef
和useImperativeHandle
暴露方法。