useRef 用于创建可变引用,访问 DOM 元素或存储不触发渲染的值。

useRef Hook 详解

useRef 用于创建可变引用,主要用于访问 DOM 元素和存储不触发渲染的值。

// 基本语法

// DOM 引用
const inputRef = useRef<HTMLInputElement>(null);

// 存储可变值
const countRef = useRef(0);

// 访问
inputRef.current?.focus();
countRef.current += 1;

示例 1: DOM 元素引用

输入框操作

视频控制

说明: useRef 可以获取 DOM 元素的引用,直接调用其原生方法。

示例 2: useRef vs useState

组件渲染次数: 1

useRef (不触发渲染)

0

数字不会变化,打开控制台查看

useState (触发渲染)

0

每次点击都会重新渲染

关键区别:

  • useRef 修改值不会触发重新渲染
  • useState 修改值会触发重新渲染
  • useRef 的值在渲染之间保持不变

示例 3: 秒表(定时器管理)

00:00.0
为什么用 useRef 存储 intervalId?
  • 定时器 ID 不需要显示在 UI 上
  • 修改它不需要触发重新渲染
  • 需要在多次渲染间保持同一个引用以便清除

示例 4: 保存上一次的值

当前值

0

上一次值

-

当前: React

上一次: -

usePrevious 自定义 Hook:

function usePrevious<T>(value: T) {
  const ref = useRef<T>();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
}

示例 5: 避免闭包陷阱

测试方法:
  1. 点击任意一个按钮
  2. 在 3 秒内修改输入框内容
  3. 观察弹出的消息是旧值还是新值

示例 6: forwardRef + useImperativeHandle

关键点:

  • forwardRef 允许父组件传递 ref 给子组件
  • useImperativeHandle 自定义暴露给父组件的方法
  • 可以隐藏实现细节,只暴露需要的接口