React useMemo Hook


React useMemo Hook 返回一个记忆值。

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

这个useMemoHook 仅在其依赖项之一更新时运行。

这可以提高性能。

这个useMemouseCallback钩子是类似的。主要区别在于useMemo返回一个记忆值并且useCallback返回一个记忆函数。您可以了解更多有关useCallback在里面useCallback章节


表现

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

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

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

例子:

性能不佳的函数。这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挂钩来记住expensiveCalculation功能。这将导致该函数仅在需要时运行。

我们可以将昂贵的函数调用包装起来useMemo

这个useMemoHook 接受第二个参数来声明依赖项。昂贵的函数仅在其依赖项发生更改时才会运行。

在下面的示例中,昂贵的函数只会在以下情况下运行:count发生了变化,而不是在添加待办事项时发生变化。

例子:

使用的性能示例useMemo钩:

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 />);

运行示例 »