useRef

245 阅读3分钟

概述

useRefReact 中的一个 Hook,用于在函数组件中创建一个可变的引用对象。这个引用对象在组件的整个生命周期中保持不变,不会因为组件的重新渲染而改变。useRef 通常用于以下几种场景:

  1. 访问DOM元素:可以通过 useRef 获取和操作 DOM 元素,类似于类组件中的 React.createRef()
  2. 存储可变值:可以用来存储任何可变值,这些值在组件的重新渲染过程中不会丢失。与 useState 不同的是,改变 useRef 的值不会触发组件重新渲染。
  3. 保持上一次渲染的值:可以用来保存某个值的前一个状态,以便在下一次渲染时使用。

示例:访问 DOM 元素

以下是一个简单的示例,展示如何使用 useRef 来访问 DOM 元素:

import React, { useRef } from 'react';

function TextInputWithFocusButton() {
  const inputEl = useRef(null);

  const onButtonClick = () => {
    // `current` 指向已挂载到 DOM 上的文本输入元素
    inputEl.current.focus();
  };

  return (
    <div>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </div>
  );
}

export default TextInputWithFocusButton;

关键点

  • 创建引用:通过调用 useRef(initialValue) 来创建一个引用对象。initialValue 是引用的初始值,通常是 null
  • 访问引用:引用对象有一个 .current 属性,可以通过它访问或修改引用的值。
  • 不触发重渲染:改变 useRef.current 属性不会导致组件重新渲染。
  • 生命周期useRef 创建的引用对象在组件的整个生命周期中保持不变。

通过 useRef,我们可以在函数组件中实现对 DOM 元素的直接操作和管理一些不需要触发重渲染的可变数据。

useRef 不仅可以用于引用 DOM 元素或存储数据,还可以用来保存对函数的引用。这种用法可以在一些特定场景下非常有用,比如当你需要在组件的生命周期内保持对函数的稳定引用时。

为什么需要对函数使用 useRef

在函数组件中,每次组件重新渲染时,函数内部定义的所有函数都会被重新创建。这可能会导致一些问题,例如:

  • 如果将函数作为依赖项传递给 useEffect 或其他 Hooks,可能会导致不必要的重新执行。
  • 如果函数被传递给子组件作为 props,子组件可能会因为接收到新的函数实例而进行不必要的重新渲染。

通过使用 useRef,可以保持对函数的稳定引用,避免这些问题。

示例:保存函数引用

下面是一个使用 useRef 来保存函数引用的示例:

import React, { useState, useRef, useEffect } from 'react';

function TimerComponent() {
  const [count, setCount] = useState(0);

  // 使用 useRef 保存对函数的引用
  const stableIncrement = useRef(() => {
    setCount((prevCount) => prevCount + 1);
  });

  useEffect(() => {
    const timerId = setInterval(() => {
      // 使用 current 属性调用函数
      stableIncrement.current();
    }, 1000);

    return () => clearInterval(timerId);
  }, []); // 空依赖数组确保 effect 只在挂载时运行

  return <div>Count: {count}</div>;
}

export default TimerComponent;

在这个例子中,我们使用 useRef 创建了一个引用 stableIncrement,并将一个函数赋值给它的 current 属性。这个函数负责更新状态 count。由于 stableIncrement 的引用在组件的整个生命周期内保持不变,我们可以在 useEffect 中安全地使用它,而不用担心它会改变。这样,useEffect 的依赖数组可以保持为空,避免了不必要的 effect 执行。

总结

使用 useRef 来保存函数的引用是一种避免函数在每次渲染时都被重新创建的有效方法。这种技术可以帮助你优化性能,特别是在将函数作为依赖项或 props 传递时,可以避免不必要的重新渲染或 effect 执行。