react中 useRef 的使用

37 阅读2分钟

useRef 可以实现一定程度的数据持久化存储,但需要明确其适用场景和局限性:

1. useRef 的特性与持久化能力

useRef 创建的是一个可变的 ref 对象,其 .current 属性可以存储任意值,且具有以下特点:

  • 跨渲染周期保存数据:组件重新渲染时,ref 对象不会被重新创建,.current 中存储的值会保持不变(除非主动修改)。
  • 不触发重新渲染:修改 .current 的值不会导致组件重新渲染,这与 useState 不同。 因此,useRef 可以将数据“持久化”存储在组件的整个生命周期内,不受渲染次数的影响。

2. 适用场景

  • 存储不需要触发渲染的持久化数据,例如:
    • 定时器 ID(如 setInterval 返回的 ID,用于后续清除)。
    • DOM 元素引用(最常见的用法)。
    • 上一次渲染时的状态或属性值(用于比较前后变化)。
    • 组件生命周期内需要保留的临时计算结果、缓存数据等。

3. 局限性

  • 并非“全局持久化”useRef 的数据仅在当前组件实例的生命周期内有效。当组件被卸载(如从 DOM 中移除)后,ref 对象及其数据会被销毁。
  • 不适合存储需要驱动 UI 渲染的数据:如果数据变化需要更新视图,必须使用 useStateuseReducer,否则修改 .current 后 UI 不会同步更新。
  • 不支持跨组件共享useRef 的数据仅在当前组件内部可见,无法直接在多个组件间共享(需结合上下文或状态管理库)。

示例:用 useRef 持久化存储定时器 ID

import { useRef, useEffect } from 'react';

function TimerComponent() {
  // 用 ref 持久化存储定时器 ID
  const timerRef = useRef(null);

  useEffect(() => {
    // 启动定时器并存储 ID
    timerRef.current = setInterval(() => {
      console.log('定时器运行中...');
    }, 1000);

    // 组件卸载时清除定时器
    return () => {
      clearInterval(timerRef.current);
    };
  }, []);

  return <div>定时器示例</div>;
}

这里 timerRef.current 存储的定时器 ID 在组件多次渲染后依然有效,确保卸载时能正确清除定时器。

总结

useRef 可以实现组件生命周期内的持久化存储,适合保存不需要触发 UI 更新的数据。但它并非用于全局持久化(如页面刷新后仍保留数据),也不能替代状态管理工具存储驱动视图的数据。