使用 React useMemo Hook

Flying
2020-03-28 / 0 评论 / 127 阅读 / 正在检测是否收录...

介绍

useMemo Hook 是一个用于优化 React 应用程序性能的 Hook。它允许你在渲染期间缓存值,以便在下一次渲染时可以重用它们。

当你使用 useMemo Hook时,它会在渲染期间计算一个值,并将其缓存起来。如果在下一次渲染时,它检测到输入值没有发生变化,它就会返回缓存的值,而不是重新计算它。这样可以极大地提高应用程序的性能。

语法

const cachedValue = useMemo(calculateValue, dependencies)

它接受两个参数:一个是要计算的函数,另一个是一个依赖数组,数组中的值会被用来比较,如果数组中的值没有发生变化,则不会重新计算,而是直接返回之前计算的结果。

useMemouseCallbac Hook 很相似。主要的区别是 useMemo 返回一个被记忆的引用值(对象、数组),而useCallback 返回一个被记忆的函数。您可以在使用 useCallback 节中了解更多有关信息。

问题

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

在这个例子中,我们有一个每次渲染都会运行的昂贵函数。当更改计数或添加 todo 时,您会注意到执行延迟。

一个性能不佳的函数。每次渲染都会运行 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>
        <button onClick={increment}> Count </button> {count}
        <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 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 />);

使用 useMemoHook 后,添加 todo 时不会运行 expensiveCalculation

1

评论 (0)

取消