useRef
是 React 提供的一个 Hook,它用于在函数组件中访问和操作 DOM 节点或存储可变的值,而这些值在组件的整个生命周期中保持不变。
作用:
- 访问 DOM 节点 :
useRef
可以获取真实的 DOM 元素,这对于需要直接操作 DOM、管理焦点、触发强制布局或进行测量等操作特别有用。 - 存储可变数据 :
useRef
还常用于存储组件内的可变数据。这些数据可以在渲染之间保持不变,但更改它们不会触发组件重新渲染。
用法:
当你创建一个 ref 时,可以将其附加到 React 元素的 ref
属性上。
ini
1const myRef = useRef(initialValue);
initialValue
是 ref 对象初始时的值。useRef
返回一个普通的 JavaScript 对象,它的current
属性被初始化为传递给useRef
的参数。
然后,可以将 myRef.current
设置为 DOM 节点或任何想要存储的值。
示例:
访问 DOM 节点:
ini
1import React, { useRef } from 'react';
2
3function TextInputWithFocusButton() {
4 const inputEl = useRef(null);
5
6 const onButtonClick = () => {
7 // `current` 属性指向了 input 元素的 DOM 节点
8 inputEl.current.focus();
9 };
10
11 return (
12 <>
13 <input ref={inputEl} type="text" />
14 <button onClick={onButtonClick}>Focus the input</button>
15 </>
16 );
17}
在此示例中,我们创建了一个输入框和一个按钮,点击按钮时,输入框会获得焦点。这里 useRef
被用来获取 input
元素的引用。
存储可变数据:
ini
1import React, { useRef } from 'react';
2
3function TimerComponent() {
4 const count = useRef(0); // count 不是一个状态,更改它不会触发组件重新渲染
5
6 const handleStart = () => {
7 count.current = setInterval(() => console.log('tick'), 1000);
8 };
9
10 const handleStop = () => {
11 clearInterval(count.current);
12 };
13
14 return (
15 <>
16 <button onClick={handleStart}>Start</button>
17 <button onClick={handleStop}>Stop</button>
18 </>
19 );
20}
在这个定时器的例子中,useRef
用于存储计时器的 ID。即使在重新渲染过程中,count.current
的值也保持不变。
使用注意事项:
- 不要滥用
useRef
:虽然useRef
可以存储任何类型的值,但并不意味着你应该使用它来代替所有的组件状态。通常,只有当你需要跨渲染周期保持可变值时,才使用useRef
。 - 合理使用 DOM 操作 :在 React 中,尽可能使用声明式代码来处理 DOM 操作。
useRef
和直接的 DOM 操作应该作为最后的手段,例如集成非 React 的库或实现焦点管理等。 - 保持引用稳定 :
useRef
在组件的整个生命周期内保持引用稳定,这意味着useRef
返回的对象在组件的每次重新渲染中都是相同的。 - 更新
current
不会触发渲染 :当你修改useRef
对象的current
属性时,这不会触发组件的重新渲染。如果你想要在更改引用值时触发渲染,应该使用useState
。 - 慎用
useRef
保存上一次的 props 或 state:有时你可能需要存储上一次的 props 或 state,这是可行的,但请小心确保不违反 React 数据流的原则。
通过使用 useRef
,你可以在函数组件中有效地管理 DOM 引用和存储可变数据,同时避免不必要的组件更新和渲染。