React useMemo Hook

React useMemo Hook 返回一个记忆值。

将记忆化视为缓存一个值,以便不需要重新计算。

useMemo Hook 仅在其依赖项之一更新时运行。

这可以提高性能。

useMemouseCallback Hooks 类似。 主要区别在于 useMemo 返回一个记忆值,而 useCallback 返回一个记忆函数。 您可以在 useCallback 章节中了解有关 useCallback 的更多信息。


性能

useMemo Hook 可用于防止昂贵的资源密集型函数不必要地运行。

在这个例子中,我们有一个在每次渲染上运行的昂贵函数。

在更改计数或添加待办事项时,您会注意到执行延迟。

实例:

性能不佳的功能。 expensiveCalculation 函数在每次渲染时运行:

import { useState } from "react";
import ReactDOM from "react-dom/client";

const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  const calculation = expensiveCalculation(count);

  const increment = () => {
    setCount((c) => c + 1);
  };
  const addTodo = () => {
    setTodos((t) => [...t, "New Todo"]);
  };

  return (
    <div>
      <div>
        <h2>My Todos</h2>
        {todos.map((todo, index) => {
          return <p key={index}>{todo}</p>;
        })}
        <button onClick={addTodo}>Add Todo</button>
      </div>
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
        <h2>Expensive Calculation</h2>
        {calculation}
      </div>
    </div>
  );
};

const expensiveCalculation = (num) => {
  console.log("Calculating...");
  for (let i = 0; i < 1000000000; i++) {
    num += 1;
  }
  return num;
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

运行实例 »


使用 useMemo

要解决这个性能问题,我们可以使用 useMemo Hook 来记忆 expensiveCalculation 函数。 这将导致函数仅在需要时运行。

我们可以用 useMemo 包装昂贵的函数调用。

useMemoHook 接受第二个参数来声明依赖项。 昂贵的函数只会在其依赖项发生变化时运行。

在下面的示例中,昂贵的函数只会在 count 更改时运行,而不是在添加 todo 时运行。

实例:

使用 useMemo Hook 的性能示例:

import { useState, useMemo } from "react";
import ReactDOM from "react-dom/client";

const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  const calculation = useMemo(() => expensiveCalculation(count), [count]);

  const increment = () => {
    setCount((c) => c + 1);
  };
  const addTodo = () => {
    setTodos((t) => [...t, "New Todo"]);
  };

  return (
    <div>
      <div>
        <h2>My Todos</h2>
        {todos.map((todo, index) => {
          return <p key={index}>{todo}</p>;
        })}
        <button onClick={addTodo}>Add Todo</button>
      </div>
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
        <h2>Expensive Calculation</h2>
        {calculation}
      </div>
    </div>
  );
};

const expensiveCalculation = (num) => {
  console.log("Calculating...");
  for (let i = 0; i < 1000000000; i++) {
    num += 1;
  }
  return num;
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

运行实例 »