使用 Ref 引用值
有些值需要在渲染之间被“记住”,但它们变化时不应该触发 UI 更新(例如定时器 id、缓存、DOM 节点)。 这时你需要的是 Ref。
获取 DOM 节点:聚焦输入框
TypeScript
import { useRef } from 'react';
export default function SearchBox() {
const inputRef = useRef<HTMLInputElement | null>(null);
function focusInput() {
inputRef.current?.focus();
}
return (
<>
<input ref={inputRef} placeholder="搜索..." />
<button onClick={focusInput}>聚焦输入框</button>
</>
);
}保存可变值:定时器 id
这个例子里,秒数需要渲染(用 State),但 interval id 不需要渲染(用 Ref)。
TypeScript
import { useRef, useState } from 'react';
export default function Stopwatch() {
const [seconds, setSeconds] = useState(0);
const intervalIdRef = useRef<number | null>(null);
function start() {
if (intervalIdRef.current !== null) return;
intervalIdRef.current = window.setInterval(() => {
setSeconds((s) => s + 1);
}, 1000);
}
function stop() {
if (intervalIdRef.current === null) return;
window.clearInterval(intervalIdRef.current);
intervalIdRef.current = null;
}
return (
<>
<p>{seconds}s</p>
<button onClick={start}>开始</button>
<button onClick={stop}>停止</button>
</>
);
}保存“上一次的值”
TypeScript
import { useEffect, useRef, useState } from 'react';
export default function PreviousValueDemo() {
const [value, setValue] = useState('');
const prevRef = useRef('');
useEffect(() => {
prevRef.current = value;
}, [value]);
return (
<>
<input value={value} onChange={(e) => setValue(e.target.value)} />
<p>当前:{value}</p>
<p>上一次:{prevRef.current}</p>
</>
);
}常见误区
- 把需要渲染的数据放到 Ref:你会发现 UI 不更新。
- 在渲染阶段读写
ref.current来做副作用:尽量把副作用放到事件处理或 Effect 中(见 使用 Effect 同步)。
下一步
- Ref 的 API 与更多细节:useRef 与 useRef 参考。
- 想理解 State 与渲染关系:State:组件的记忆。
动手练习
运行并修改下面的组件,熟悉交互式示例的编辑与预览。
🌐浏览器运行