React中useRef钩子的使用技巧
创作时间:
作者:
@小白创作中心
React中useRef钩子的使用技巧
引用
1
来源
1.
https://developer.aliyun.com/article/1629174
在React中,useRef是一个非常有用的Hook,它可以让你在组件的生命周期内保留一些数据,而不会引起组件的重新渲染。本文将从基础概念入手,逐步深入到useRef的常见问题、易错点及如何避免这些问题,并通过代码示例来帮助理解其应用场景和实现方式。
基础概念
什么是useRef?
useRef是一个React Hook,它返回一个可变的ref对象,其.current属性被初始化为传递的参数(initialValue)。返回的ref对象在组件的整个生命周期内保持不变。
基本用法
import React, { useRef } from 'react';
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
export default TextInputWithFocusButton;
在这个例子中,useRef用于获取对输入框的引用,以便在按钮点击时将其聚焦。
常见问题与易错点
1. 误用useRef来存储状态
useRef不应该用来存储组件的状态。React提供了useState和useReducer来管理状态,而useRef主要用于保存那些不需要触发重新渲染的数据。
错误示例
import React, { useRef, useEffect } from 'react';
function Counter() {
const countRef = useRef(0);
useEffect(() => {
countRef.current++;
});
return (
<div>
Count: {countRef.current}
</div>
);
}
export default Counter;
在这个例子中,countRef用于存储计数器的值,但由于countRef的变化不会触发重新渲染,因此界面上的计数器值不会更新。
正确示例
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<div>
Count: {count}
</div>
);
}
export default Counter;
2. 忘记初始化ref
在使用useRef时,忘记初始化ref可能会导致undefined错误。
错误示例
import React, { useRef } from 'react';
function Example() {
const myRef = useRef();
useEffect(() => {
console.log(myRef.current.value); // 可能会抛出错误
}, []);
return (
<input ref={myRef} type="text" />
);
}
export default Example;
正确示例
import React, { useRef, useEffect } from 'react';
function Example() {
const myRef = useRef(null);
useEffect(() => {
console.log(myRef.current?.value); // 使用可选链操作符
}, []);
return (
<input ref={myRef} type="text" />
);
}
3. 在函数组件中使用ref
在函数组件中使用ref时,需要确保正确地传递ref。
错误示例
import React, { useRef } from 'react';
function CustomInput(props) {
return <input {...props} />;
}
function App() {
const inputRef = useRef(null);
return (
<CustomInput ref={inputRef} />
);
}
export default App;
正确示例
import React, { useRef, forwardRef } from 'react';
const CustomInput = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
function App() {
const inputRef = useRef(null);
return (
<CustomInput ref={inputRef} />
);
}
export default App;
如何避免这些问题
- 明确用途:
useRef用于保存那些不需要触发重新渲染的数据,不要用它来管理状态。 - 初始化ref:始终初始化ref,避免
undefined错误。 - 使用可选链操作符:在访问ref的属性时,使用可选链操作符(
?.)来防止潜在的undefined错误。 - 正确传递ref:在自定义组件中使用
forwardRef来正确传递ref。
进阶用法
1. 保存回调函数
useRef可以用于保存回调函数,以避免在每次渲染时都创建新的函数引用。
import React, { useRef, useEffect } from 'react';
function UseRefCallbackExample() {
const callbackRef = useRef(null);
useEffect(() => {
callbackRef.current = handleScroll;
});
const handleScroll = () => {
console.log('Scrolled');
};
useEffect(() => {
window.addEventListener('scroll', callbackRef.current);
return () => {
window.removeEventListener('scroll', callbackRef.current);
};
}, []);
return (
<div>
Scroll down to see the effect.
</div>
);
}
export default UseRefCallbackExample;
2. 保存定时器ID
useRef可以用于保存定时器ID,以便在组件卸载时清除定时器。
import React, { useRef, useEffect } from 'react';
function TimerExample() {
const timerIdRef = useRef(null);
useEffect(() => {
timerIdRef.current = setInterval(() => {
console.log('Tick');
}, 1000);
return () => {
clearInterval(timerIdRef.current);
};
}, []);
return (
<div>
Timer is running...
</div>
);
}
export default TimerExample;
总结
useRef是一个非常强大的Hook,可以帮助你在组件的生命周期内保留一些数据,而不会引起组件的重新渲染。通过本文的介绍和代码示例,希望你能更好地理解和应用useRef,并在实际开发中避免常见的问题和易错点。
热门推荐
AI智能体(Agent)的发展历程:初学者必备-从规则到自主智能
清洗三元催化器有什么作用?
网上公证如何操作?全流程指南及法律风险提示
虾解冻后变黑的原因及预防方法
传说中的这些龙有何区别?
Everything搜索神器:秒级检索背后的黑科技
玩转汉语,谐音梗带你笑破肚皮!
阴历与阳历的区别及其在生活中的重要性探讨
风电光伏业环保新规正酝酿,将实施全生命周期管理
一文读懂 | 残疾人退休政策全解析
一直流汗又感觉冷?可能是这5种疾病在作祟
光催化反应器规模化应用面临的挑战与解决方案:从实验室到工业化的跨越
程序员的健康危机:如何在高强度工作下保持活力?
解讀|A股連升兩周 專家:牛市第二波行情顯現雛形
盘点宇宙中那些恐怖的天体,最恐怖的天体你肯定想不到!
DeepSeek-V3 多token预测解读
JAMA子刊重磅综述:详解PARP抑制剂在乳腺癌中的应用
老话说:家庭有这些特点,子女必然有出息!
未来10年西安人口增200万?从国土空间规划看西安发展方向
安全工程属于什么专业类别 未来发展方向
重磅归来!IL-2药物研发新突破
5G技术能为智能家居带来什么?
高考数学高效提分方法及技巧汇总
毕业了,助学贷款该怎么还?最全攻略都在这!
小县城电商外包客服新蓝海:地域人力优势,薪资差造就盈利新引擎!
南昌至长沙旅行指南:穿越古迹与自然的双城记
派拉蒙裁决:重塑美国电影产业的里程碑事件
一口白米饭=血糖飙升83%?揭开食物GI值的隐藏密
什么运动对膝盖的损害最小
肺腺癌的原因及症状