发布于 2026-01-06 1 阅读
0

了解 React 中的 useMemo 钩子是什么

了解 React 中的 useMemo

useMemo hook 是什么?

在上一篇文章中,我们讨论了 useContext hook,并探讨了 useContext 的一些使用场景。在本文中,我们将讨论 useMemo,它为何重要以及何时使用它。让我们直接进入正题。

useMemo hook 是什么?

useMemo hook 具有记忆功能,它会缓存函数返回的值。为了更好地理解 useMemo,我们将了解一种名为 memoization 的 JavaScript 技术。

什么是记忆化

简单来说,记忆化是一种通过将复杂函数调用的结果存储到缓存中,并在下次调用该函数时返回缓存值来提高程序性能的技术。例如,假设我有一个加法函数,它接受两个参数,并在返回两个值的和之前执行大量复杂的运算。如果我对这个加法函数进行记忆化,就会发生以下情况:
当我第一次调用加法函数并传入 2 和 3 时,它会执行所有复杂的运算并返回 5,然后将该值存储到缓存中。下次我再次调用同一个加法函数并传入相同的值 2 和 3 时,程序不会执行所有复杂的运算,而是记住我之前传入过 2 和 3,然后直接返回相同的值 5。

我见过那个动图。

这样做的好处是,由于该函数之前已经使用相同的输入被调用过,因此程序不会花费所有时间来运行该函数。

返回使用备忘录

useMemo钩子函数接受一个回调函数和一个依赖项(例如 useEffects),并返回一个记忆化的值。只有当传入的任何依赖项的值发生变化时,它才会触发组件重新渲染。

const complexFunction = useMemo(() => {
  ...
},[aValue]);
Enter fullscreen mode Exit fullscreen mode

何时使用

只有当运行一个开销非常大的函数时,才应该使用这个钩子。你的函数一开始应该运行良好,之后再考虑添加这个钩子。

我们来看一个 useMemo 的工作原理示例。
我个人不太常用这个钩子,但为了演示,我们(故意)使用一个循环,稍微减慢一下运行速度。PS 请勿在家尝试!
哈哈

import React, {useState} from 'react';

const thisFunctionWillSlowDownOurApp = (num1, num2) => {
/* this might cause an infinite loop. if you're using codesandbox */
const thisFunctionWillSlowDownOurApp = (num1, num2) => {
  for (let i = 0; i <= 10001; i++) {}
  console.log('That took a while');
  return +num1 + +num2;
 }

export default function App() {
  const [numToAdd, setNumToAdd] = useState(0);
  const [num2, set2] = useState(0);

  const addedValue = thisFunctionWillSlowDownOurApp(numToAdd);

  return (
    <div className="App">
      <input type="number" 
        value={numToAdd} 
        onChange={(e) => setNumToAdd(e.target.value)} />

      <input type="number" 
        value={num2} 
        onChange={(e) => set2(e.target.value)} />

      <div>{addedValue}</div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

我们已经可以看到这段代码存在问题(请注意,此示例仅用于演示目的)。我们也可以看到程序存在性能问题。而这正是 useMemo 的作用所在。

为了改进这段代码,我们将使用 useMemo。

// import useMemo
import React, {useState, useMemo} from 'react';

const thisFunctionWillSlowDownOurApp = (num1, num2) => {
/* this might cause an infinite loop. if you're using codesandbox */
const thisFunctionWillSlowDownOurApp = (num1, num2) => {
  for (let i = 0; i <= 10001; i++) {}
  console.log('That took a while');
  return +num1 + +num2;
// the + before num1 and num2 will convert it to an integer
 }

export default function App() {
  const [numToAdd, setNumToAdd] = useState(0);
  const [num2, set2] = useState(0);

// Usage
  const addedValue = useMemo(() => {
    return thisFunctionWillSlowDownOurApp(numToAdd, num2);
  }, [numToAdd, num2]);


  return (
    <div className="App">
      <input type="number" 
        value={numToAdd} 
        onChange={(e) => setNumToAdd(e.target.value)} />

      <input type="number" 
        value={num2} 
        onChange={(e) => set2(e.target.value)} />

      <div>{addedValue}</div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

这样,当同一个值传递两次时,循环就不会运行两次。

为什么你不应该过度使用钩子

这个钩子函数使用了复杂的逻辑,所以过度使用它可能会对你的组件造成弊大于利的影响。此外,React 文档中也提到,React 有时可能会“忘记”一些之前缓存的值,并在下次渲染时重新计算,因此即使不使用 useMemo,你的函数也应该能够正常工作。

结论

useMemo 的使用场景因工作内容而异,您可能“可能”不会遇到需要使用它的问题。但一旦需要,它确实能显著提升性能。不过,我建议您在确定没有必要的情况下不要使用它。

以上就是 useMemo 的基本用法。希望这篇文章能帮助你理解这个钩子。在下一篇文章中,我们将继续探讨这个useRef钩子。

你还有其他建议或疑问吗?欢迎在评论区留言,我会很乐意解答。祝你一切顺利,注意安全!✌🏾

文章来源:https://dev.to/ilizette/understanding-usememo-in-react-1dn