标准答案
- useRef 最常见用途是拿 DOM 节点,例如聚焦输入框、测量尺寸或接入第三方库。
- useRef 的对象引用在组件生命周期内保持稳定,current 可以被修改,但不会触发组件重新渲染。
- 它可以保存 timer id、AbortController、WebSocket、图表实例、编辑器实例等不直接参与渲染的数据。
- 它也可以保存最新 props 或 state,供异步回调读取,避免旧闭包问题。
- 如果一个值变化后需要反映到 UI,就不应该只放 ref,应使用 state 或外部状态管理。
题目解析
useRef 的关键特性是“稳定引用”和“不触发渲染”。这使它适合保存命令式对象和非 UI 状态。
DOM ref 只是 useRef 的一个场景。复杂组件里,ref 经常用于保存上一次值、请求控制器和第三方实例。
ref 不是 state 的替代品。凡是 UI 需要根据它变化,就要谨慎使用 ref。
代码示例
下面用 ref 保存最新回调,避免事件监听器反复解绑绑定。
TSX
function useWindowKeydown(onKeydown: (event: KeyboardEvent) => void) {
const handlerRef = useRef(onKeydown)
useEffect(() => {
handlerRef.current = onKeydown
}, [onKeydown])
useEffect(() => {
function handleKeydown(event: KeyboardEvent) {
handlerRef.current(event)
}
window.addEventListener('keydown', handleKeydown)
return () => window.removeEventListener('keydown', handleKeydown)
}, [])
}常见误区
- 把需要驱动 UI 的数据放进 ref,修改后页面不更新。
- 认为 useRef 只能拿 DOM,不知道它能保存跨渲染的可变值。
- 用 ref 绕过 React 数据流,导致组件外部无法理解真实状态。