您的位置:

useMemo——提高React性能的利器

一、什么是useMemo

React中提供了一种优化组件性能的钩子函数——useMemo。它可以帮助我们避免在每次渲染时都执行的昂贵计算。

useMemo钩子函数接收两个参数:计算函数和依赖项数组。计算函数会在渲染期间执行,依赖项数组中的值是用来比较的,如果某个依赖项发生变化,useMemo会重新计算数值。否则,它将返回上一次计算结果的值。

示例代码:

  const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

二、如何使用useMemo

1、需要优化渲染的函数

因为useMemo是一个可以计算复杂值的钩子函数,所以只有当你的组件渲染的元素个数非常多或者需要进行复杂计算时,你才需要使用useMemo来进行性能优化。

示例代码:

  function App() {
    const arr = [1,2,3,4,5];
    const memoizedArr = useMemo(() => {
      return arr.map(item => item * item)
    }, [arr]);

    return (
      <div>
        <ul>
          {memoizedArr.map(item => <li>{item}</li>)}
        </ul>
      </div>
    );
  }

2、依赖项数组使用

useMemo的第二个参数中传递的是一个依赖项数组。这个数组中传递的值会在每次渲染时与上次的值进行比较。只有当它们不同时,useMemo才会重新计算数值。

示例代码:

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

    const memoizedValue = useMemo(() => {
      const sum = Array.from({ length: count }, (_, index) => index + 1).reduce((a, b) => {
        return a + b;
      });
      return sum;
    }, [count]);

    return (
      <div>
        <h3>count:{count}</h3>
        <button onClick={() => setCount(count + 1)}>add count</button>
        <span>memoizedValue:{memoizedValue}</span>
      </div>
    );
  }

3、将useMemo用在useEffect中

useMemo还可以用来优化像useEffect这样的副作用钩子函数。下面的示例展示了如何使用useMemo来减少不必要的渲染。

示例代码:

  function App3() {
    const [count, setCount] = useState(0);
    const [step, setStep] = useState(1);

    const memoizedValue = useMemo(() => ({ count }), [count]);

    useEffect(() => {
      console.log('count:', count);
    }, [memoizedValue]);

    return (
      <div>
        <h3>count:{count}</h3>
        <h3>step:{step}</h3>
        <button onClick={() => setCount(count + step)}>add count</button>
        <button onClick={() => setStep(step + 1)}>add step</button>
      </div>
    );
  }

三、useMemo使用的常见错误

1、忽略依赖项

为了使useMemo正常工作,必须在第二个参数中传递所有相关的依赖项。如果忽略了一个重要的依赖项,则useMemo将不会执行预期的更新操作。

示例代码:

  function App4() {
    const [count, setCount] = useState(0);
    const [step, setStep] = useState(1);

    const memoizedValue = useMemo(() => {
      const sum = Array.from({ length: count }, (_, index) => index + 1).reduce((a, b) => {
        return a + b;
      });
      return sum;
    }, []); // 这里忽略了count,所以memoizedValue永远不会变化

    return (
      <div>
        <h3>count:{count}</h3>
        <h3>step:{step}</h3>
        <button onClick={() => setCount(count + step)}>add count</button>
        <button onClick={() => setStep(step + 1)}>add step</button>
        <span>memoizedValue:{memoizedValue}</span>
      </div>
    );
  }

2、过度使用useMemo

虽然useMemo可以优化组件的性能,但是过度使用它会导致代码更加复杂。有时候,完全没有必要优化某些计算,因为它们的成本非常低。

示例代码:

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

    // count的平方数
    const memoizedValue = useMemo(() => {
      return count ** 2;
    }, [count]);

    // 仅仅只是count的显示
    const memoizedValue2 = useMemo(() => {
      return `count:${count}`;
    }, [count]);

    return (
      <div>
        <h3>{memoizedValue2}</h3>
        <p>memoizedValue:{memoizedValue}</p>
        <button onClick={() => setCount(count + 1)}>add count</button>
      </div>
    );
  }

四、总结

useMemo是一个非常有用的钩子函数,可以帮助我们在React应用程序中提高性能。但是,如果不适当地使用它,会导致代码变得更加难以阅读和理解。因此,在使用useMemo之前,请仔细考虑您要优化的值是否真的太昂贵,是否需要优化。