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,并在实际开发中避免常见的问题和易错点。
热门推荐
养胃食谱大揭秘:小米粥、蒸蛋羹、红枣汤
胃炎患者如何科学养生?从饮食到运动,这份实用指南请收好!
世界压疮预防日:科学清洁褥疮创面
老年人褥疮护理指南:从一级到四级
冬季护理神器:减压垫防褥疮
冬季长期卧床患者如何预防褥疮?
三管齐下治失眠:生活习惯、心理疏导与药物治疗
疫情恐慌怎么办?专家推荐六大应对方案
牛奶、香蕉、核桃:十大助眠食物推荐及功效
学会情绪管理,挽救濒临破裂的友谊
青少年抑郁率超两成,及早干预是关键
进入心流状态:让工作学习事半功倍的专注秘诀
傻瓜机热潮来袭:数字排毒正当时
新文化领袖与言情作家:两位传奇人物的婚姻抉择
财联社主办半导体行业沙龙,企业与资本共话产业新局
香港去珠海最快时间和最佳交通方式
积极回应澳门居民关切!合作区探讨创新粤澳合作社会服务模式
孩子说“我不想上学”,除了坚持、妥协,我们还能做什么?
元旦出行必看!广州、上海、天津限行全攻略
养老护理员教你科学预防褥疮
情绪管理,让你远离胃炎困扰
长期卧床患者如何有效预防压疮?
侧翻固定垫:预防褥疮的护理神器
百年天津站:京滨城际助力,打造京津冀空铁联运新枢纽
麦韵屏教你:如何通过自我检查发现胃炎
麦韵屏副主任医师教你饮食调理胃炎
纳粹德国军党之争:弗里奇为何要打击希姆莱
符离集烧鸡年产值超20亿,成乡村振兴新引擎
万宁石梅湾亲子游全攻略:海滩、酒店、活动一网打尽
冠豸山:龙岩市的自然瑰宝