繁体   English   中英

useMemo 与 useEffect + useState

[英]useMemo vs. useEffect + useState

使用useMemo (例如用于密集函数调用)而不是使用useEffectuseState的组合有useEffect useState

这里有两个自定义钩子,乍一看完全相同,除了useMemo的返回值在第一次渲染时为null

在 CodeSandbox 上查看

useEffect & useState

import { expensiveCalculation } from "foo";

function useCalculate(someNumber: number): number {
  const [result, setResult] = useState<number>(null);

  useEffect(() => {
    setResult(expensiveCalculation(someNumber));
  }, [someNumber]);

  return result;
}

使用备忘录

import { expensiveCalculation } from "foo";

function useCalculateWithMemo(someNumber: number): number {
    return useMemo(() => {
        return expensiveCalculation(someNumber);
    }, [someNumber]);
};

每次他们的参数someNumber改变时,两者都会计算结果, useMemo的记忆在哪里开始?

useEffectsetState将在每次更改时导致额外的渲染:第一个渲染将“滞后”与陈旧数据,然后它将立即使用新数据排队附加渲染。


假设我们有:

function expensiveCalculation(x) { return x + 1; }; // Maybe I'm running this on a literal potato

让我们假设someNumber最初是 0:

  • useMemo版本立即呈现1
  • useEffect版本渲染null ,然后在组件渲染效果后运行,更改状态,并使用1将新渲染排队。

然后,如果我们将someNumber更改为 2:

  • useMemo运行并呈现3
  • useEffect版本运行,并再次渲染1 ,然后触发效果并且组件以正确的3值重新运行。

expensiveCalculation运行的频率而言,两者具有相同的行为,但useEffect版本导致两倍的渲染,这对性能不利,因为其他原因。

另外,IMO 的useMemo版本更清晰、更易读。 它不会引入不必要的可变状态并且具有更少的移动部件。

所以你最好在这里使用useMemo

我认为在它们之间进行选择时,您应该考虑两个要点。

  1. 函数调用的时间。

useEffect在组件渲染后调用,因此您可以从中访问 DOM。 例如,如果您想通过 refs 访问 DOM 元素,这很重要。

  1. 语义保证。

useEffect保证在依赖项没有改变的情况下它不会被触发。 useMemo不提供此类保证。

React 文档中所述,您应该将 useMemo 视为纯优化技术。 即使您用常规函数调用替换 useMemo,您的程序也应该继续正常工作。

useEffect + useState可用于控制更新。 甚至打破循环依赖并防止无限更新循环。

我想说除了异步性质之外,它们的设计方式可能存在一些差异。

useEffect是一个集体调用,无论异步与否,它都是在所有组件渲染后收集的。

useMemo是一个本地调用,它只与这个组件有关。 您可以将useMemo视为另一个赋值语句,有时可以跳过赋值语句。

这意味着, useMemo是更为迫切,然后useLayoutEffect和最后被useEffect ,特别是当输入是来自一个道具。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM