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
,并在实际开发中避免常见的问题和易错点。
热门推荐
《叫我大掌柜》零氪攻略之如何提升赚速
如何预防脂肪肝?脂肪肝患者的饮食建议?脂肪肝患者可以吃巧克力吗?
兴平UPS不间断电源怎么连接?
菲律宾宿务岛最佳旅游季节及注意事项
数学公式可视化技术
《清明上河图密码》古装悬疑剧“天花板”,这些“配角”堪称一绝
卫生间下水道被水泥堵了怎么办?四种实用疏通方法
10款——最常用的3D打印金属材料
春季种番茄,怎么种出草莓番茄、铁皮番茄,是不是水肥越少越好?
动起来、健康来!请收好这份“春节力量训练指南”
彼得林奇PEG价值选股策略:原理、回测与应用
米饭的正确打开方式:从选米到焖饭的完整攻略
顺风车怎样顺利接到拼车订单?这种接单方式有哪些技巧?
探访全球首座第四代核电站:不会熔毁的核反应堆
秋冬智能马桶使用率上升,这份使用注意事项请查收
追寻匈奴的足迹:从古至今的民族融合
做了N年眼保健操还是近视了,原因竟然是……
海为PLC/HMI/云/手机APP在现代水产农业养殖上的应用
复旦教授评国产光刻机:虽落后20年,但自主可控优势明显
智慧农业再上新丨南果北种 茄子上树——北大荒打造农业“黑科技”
上海机场联络线最新消息:票价机制公布,年底即将开通
大六壬的断课思路与步骤
【人文山水·时光峰峦】探索世界自然遗产施秉云台山,体验自然与文化的双重秘境
时间与空间的奥秘:从亚里士多德到量子力学的探索之旅
技术革新:企业降本增效的关键突破点
人死前一天最怕什么
日本学校女生 “光腿” 奇观:寒潮来袭,为啥校规仍禁止穿裤袜?
蜀锦织造技艺:国家级非物质文化遗产
守护青少年的心理健康,这些知识要知道!
跨越障碍:提升小学英语成绩的实用策略