React useMemo Hook(钩子)

React useMemo 钩子返回一个已记忆的值。

可以将 记忆化 视为缓存一个值,这样就不需要重新计算它。

useMemo 钩子仅在其一个依赖项更新时运行。

这样可以提高性能。

useMemouseCallback 钩子类似。主要区别在于 useMemo 返回一个 已记忆 的值,useCallback 返回一个 已记忆 的函数。

您可以在 useCallback 一章中学习有关 useCallback 的更多知识。


执行

useMemo 钩子可以用来防止重量级的、资源密集型的函数不必要地运行。

在本例中,我们有一个在每个渲染上运行的重量级函数。

更改计数或添加 todo 时,您会注意到执行有延迟。

实例:

一个性能差的功能。expensiveCalculation 函数在每个渲染上运行:

  1. import { useState } from "react";
  2. import ReactDOM from "react-dom";
  3. const App = () => {
  4. const [count, setCount] = useState(0);
  5. const [todos, setTodos] = useState([]);
  6. const calculation = expensiveCalculation(count);
  7. const increment = () => {
  8. setCount((c) => c + 1);
  9. };
  10. const addTodo = () => {
  11. setTodos((t) => [...t, "New Todo"]);
  12. };
  13. return (
  14. <div>
  15. <div>
  16. <h2>My Todos</h2>
  17. {todos.map((todo, index) => {
  18. return <p key={index}>{todo}</p>;
  19. })}
  20. <button onClick={addTodo}>Add Todo</button>
  21. </div>
  22. <hr />
  23. <div>
  24. Count: {count}
  25. <button onClick={increment}>+</button>
  26. <h2>Expensive Calculation</h2>
  27. {calculation}
  28. </div>
  29. </div>
  30. );
  31. };
  32. const expensiveCalculation = (num) => {
  33. console.log("Calculating...");
  34. for (let i = 0; i < 1000000000; i++) {
  35. num += 1;
  36. }
  37. return num;
  38. };
  39. ReactDOM.render(<App />, document.getElementById("root"));

使用 useMemo

为了解决这个性能问题,我们可以使用 useMemo 钩子来记忆 expensiveCalculation 函数。这将使该函数仅在需要时运行。

我们可以用 useMemo 包含重量级的函数调用。

useMemo Hook(钩子)接受第二个参数来声明依赖项。重量级的函数只有在其依赖项发生更改时才会运行。

在下面的示例中,重量级的函数将仅在 更改 计数时运行,而不会在添加 todo 时运行。

实例:

使用 useMemo Hook 执行实例:

  1. import { useState, useMemo } from "react";
  2. import ReactDOM from "react-dom";
  3. const App = () => {
  4. const [count, setCount] = useState(0);
  5. const [todos, setTodos] = useState([]);
  6. const calculation = useMemo(() => expensiveCalculation(count), [count]);
  7. const increment = () => {
  8. setCount((c) => c + 1);
  9. };
  10. const addTodo = () => {
  11. setTodos((t) => [...t, "New Todo"]);
  12. };
  13. return (
  14. <div>
  15. <div>
  16. <h2>My Todos</h2>
  17. {todos.map((todo, index) => {
  18. return <p key={index}>{todo}</p>;
  19. })}
  20. <button onClick={addTodo}>Add Todo</button>
  21. </div>
  22. <hr />
  23. <div>
  24. Count: {count}
  25. <button onClick={increment}>+</button>
  26. <h2>Expensive Calculation</h2>
  27. {calculation}
  28. </div>
  29. </div>
  30. );
  31. };
  32. const expensiveCalculation = (num) => {
  33. console.log("Calculating...");
  34. for (let i = 0; i < 1000000000; i++) {
  35. num += 1;
  36. }
  37. return num;
  38. };
  39. ReactDOM.render(<App />, document.getElementById("root"));

分类导航