用还是不用useMemo,这是一个问题

2,387 阅读3分钟

React Hooks的useMemo到底有什么用

useMemo是React提供的一个用于优化性能的Hook,它的作用是用来缓存计算结果,避免重复计算。可以将一些昂贵的计算操作放到useMemo函数中,这样只有在依赖项发生变化时才会重新计算,从而提高应用程序的性能。

1-useMemo的语法

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

其中,第一个参数是一个函数,用于执行昂贵的计算操作,第二个参数是一个数组,包含了所有的依赖项。当依赖项发生变化时,useMemo函数会重新计算值,否则它会返回缓存的值。

2-useMemo函数缓存计算结果

import React, { useState, useMemo } from 'react';
function App() {
  const [count, setCount] = useState(0);
  const [factorial, setFactorial] = useState(1);
  const calculateFactorial = (number) => {
    let result = 1;
    for (let i = 1; i <= number; i++) {
      result *= i;
    }
    return result;
  };
  const memoizedFactorial = useMemo(() => calculateFactorial(count), [count]);
  const handleIncrement = () => {
    setCount(count + 1);
  };
  const handleCalculateFactorial = () => {
    setFactorial(memoizedFactorial);
  };
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleIncrement}>Increment</button>
      <p>Factorial: {factorial}</p>
      <button onClick={handleCalculateFactorial}>Calculate Factorial</button>
    </div>
  );
}
export default App;

在上面的代码中,我们定义了一个计算阶乘的函数calculateFactorial,它用于计算当前计数器的阶乘。然后,我们在useMemo函数中调用该函数,将计算结果缓存起来。每当计数器的值发生变化时,useMemo函数会重新计算阶乘,并将计算结果缓存起来。然后,我们在点击“Calculate Factorial”按钮时,将缓存的阶乘值设置为当前的阶乘值。这样就可以避免重复计算,提高应用程序的性能。

3-反面案例

当使用useMemo的时候,需要注意以下几点,否则可能会出现错误的使用方式:

3.1-使用useMemo来优化简单的计算操作

例如简单的加减乘除运算,这样会增加代码的复杂度,反而会降低性能。

import React, { useMemo } from 'react';
function App() {
  const a = 10;
  const b = 20;
  const memoizedSum = useMemo(() => a + b, [a, b]);
  return (
    <div>
      <p>Sum: {memoizedSum}</p>
    </div>
  );
}
export default App;

3.2-将useMemo用于副作用操作

例如修改DOM或者发送网络请求等操作,这些操作应该放在useEffect中进行。

import React, { useMemo } from 'react';
function App() {
  const memoizedMessage = useMemo(() => {
    const message = 'Hello world';
    document.title = message;
    return message;
  }, []);
  return (
    <div>
      <p>{memoizedMessage}</p>
    </div>
  );
}
export default App;

3.3-将整个组件用useMemo包裹

这样会导致组件的所有状态都被缓存,当任何一个状态改变时,整个组件都需要重新渲染,反而会降低性能。

import React, { useState, useMemo } from 'react';
function App() {
  const [count, setCount] = useState(0);
  const memoizedState = useMemo(() => {
    return { count, setCount };
  }, [count, setCount]);
  const handleIncrement = () => {
    memoizedState.setCount(memoizedState.count + 1);
  };
  return (
    <div>
      <p>Count: {memoizedState.count}</p>
      <button onClick={handleIncrement}>Increment</button>
    </div>
  );
}
export default useMemo(App);

3.4-混用useMemouseCallback

它们虽然都可以用于缓存计算结果,但是它们的作用不同,useMemo用于缓存值,useCallback用于缓存函数。

import React, { useState, useMemo, useCallback } from 'react';
function App() {
  const [count, setCount] = useState(0);
  const memoizedValue = useMemo(() => {
    return count * 2;
  }, [count]);
  const memoizedFunction = useCallback(() => {
    setCount(count + 1);
  }, [count]);
  return (
    <div>
      <p>Value: {memoizedValue}</p>
      <button onClick={memoizedFunction}>Increment</button>
    </div>
  );
}
export default App;

总的来说,需要遵循useMemo的使用规范,避免出现上述错误的使用方式,以确保代码的正确性和性能的优化。