📜  用于差异的 useRef (1)

📅  最后修改于: 2023-12-03 15:40:53.886000             🧑  作者: Mango

用于差异的 useRef

useRef 是 React 提供的一个 hook 函数,用于创建一个可以在组件的生命周期中持久化的引用。通常情况下,我们会使用 useRef 创建一个组件的引用,然后在需要的时候直接使用该引用来访问组件的 DOM 元素,并进行相关操作。

但是,useRef 还有一个非常重要的用途,那就是用于处理差异。在 React 中,当组件状态发生变化时,React 会比较前后状态的差异,然后重新渲染组件。这个过程中,React 会进行一系列优化,包括直接复用之前渲染过的 DOM 元素,而不是重新创建一份。但是,当我们需要直接去修改 DOM 元素,或者进行一些需要操作 DOM 元素的操作时,就需要避免 React 的复用优化,强制使用新的 DOM 元素。这个时候,useRef 就可以发挥作用了。

useRef 的用法

useRef 的基本用法非常简单,只需要调用该函数并传入初始化值即可:

const myRef = useRef(initialValue);

返回的 myRef 对象包含了一个 current 属性,用于存储组件的引用。之后可以直接使用 myRef.current 来访问该引用。

使用 useRef 处理差异

通常情况下,我们在使用 useEffect 时,会传入一个依赖数组,React 会通过比较这个数组的值来判断是否需要重新运行该 useEffect 里的代码。如果数组中的值发生变化,就会重新运行,否则就跳过。但是,当我们需要强制使用新的 DOM 元素时,就需要在依赖数组中加入一个不变的值,这个值可以使用 useRef 来存储。

举个例子,假设我们有一个组件需要在初始化时添加一个 click 事件监听器:

import { useRef, useEffect } from 'react';

function MyComponent() {
  const ref = useRef();

  useEffect(() => {
    ref.current.addEventListener('click', handleClick);

    return () => {
      ref.current.removeEventListener('click', handleClick);
    };
  }, [ref]);

  function handleClick() {
    console.log('click!');
  }

  return <div ref={ref}>My Component</div>;
}

但是,如果我们同时需要在该组件的一个状态变化时,强制使用新的 DOM 元素,那么就需要在 useEffect 的依赖数组中加入一个不变的值,比如 ref,这样就可以每次都使用新的 DOM 元素:

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

function MyComponent() {
  const ref = useRef();
  const [count, setCount] = useState(0);

  useEffect(() => {
    ref.current.addEventListener('click', handleClick);

    return () => {
      ref.current.removeEventListener('click', handleClick);
    };
  }, [ref, count]);

  function handleClick() {
    console.log('click!');
  }

  return (
    <div ref={ref}>
      My Component
      <button onClick={() => setCount(count + 1)}>Click Me</button>
    </div>
  );
}

此时,每次 count 的值发生变化时,useEffect 都会重新运行一次,而且由于 ref 在每次渲染时都保持不变,因此每次都会使用不同的 DOM 元素。

总结

useRef 的本质是创建一个可以在组件的生命周期中持久化的引用,并且可以在需要访问组件的 DOM 元素时直接使用该引用。此外,useRef 还可以用于处理差异,强制使用新的 DOM 元素。有了这个知识,我们就可以更加灵活地处理组件的状态和 DOM 元素了!