提问者:小点点

useMemo vs. use效果useState


使用useMemo(例如,对于密集型函数调用)而不是使用use效应useState的组合有什么好处吗?

这里有两个自定义钩子,第一眼看上去完全一样,除了useMemo的返回值在第一次渲染时为null之外:

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改变时,都会计算结果,usemo的记忆在哪里?


共3个答案

匿名用户

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

假设我们有:

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

假设someNumber最初为0:

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

然后,如果我们将某些数字更改为2:

  • 运行usemo并呈现3
  • useffect版本运行,并再次呈现1,然后效果触发,组件以正确的3值重新运行

忙乱计算的运行频率而言,两者具有相同的行为,但是use效应版本会导致两倍的渲染,这对其他原因的性能不利。

另外,IMO的useMemo版本更干净、可读性更强。它不会引入不必要的可变状态,并且运动部件更少。

因此,您最好在此处使用usemo

匿名用户

我认为在选择它们之间应该考虑两个要点。

  1. 调用函数的时间

useffect在呈现组件后调用,所以您可以从中访问DOM。例如,如果希望通过引用访问DOM元素,这一点很重要。

useffect保证在依赖项未更改时不会触发它<代码>使用备忘录不提供此类保证。

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

useffectuseState可用于控制更新。甚至可以打破循环依赖,防止无限更新循环。

匿名用户

我想说的是,除了异步特性之外,它们的设计方式可能会有所不同。

无论是否异步,它都是在呈现所有组件后收集的。

useMemo是一个本地调用,它只与此组件有关。您可以将useMemo视为另一个赋值语句,它具有使用上次更新赋值的好处。

这意味着,usemo更紧急,然后是useLayoutEffect,最后一个是useffect