reactjs 使用备忘录与使用效果+使用状态

v6ylcynt  于 2022-11-29  发布在  React
关注(0)|答案(4)|浏览(194)

使用useMemo(例如,对于密集的函数调用)而不是使用useEffectuseState的组合有什么好处吗?
这里有两个自定义钩子,它们在第一次渲染时的工作原理完全相同,除了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改变时,两者都计算结果,useMemo的记忆在哪里起作用?

gg58donl

gg58donl1#

useEffectsetState将在每次更改时导致额外渲染:第一个渲染将“落后”于过时的数据,然后它将立即使用新的数据排队另外一个渲染。
假设我们有:

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

假设x最初为0:

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

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

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

expensiveCalculation的运行频率而言,这两个版本的行为完全相同,但useEffect版本导致的渲染量是expensiveCalculation版本的两倍,由于其他原因,这对性能不利。
另外,useMemo版本更干净,可读性更强,IMO。它没有引入不必要的可变状态,移动部件更少。
所以最好在这里使用useMemo

cuxqih21

cuxqih212#

我认为在两者之间进行选择时,有两个要点你应该考虑。
1.调用函数时间
useEffect在呈现组件后调用,因此您可以从该组件访问DOM例如,如果您希望通过引用访问DOM元素,这一点很重要
1.语义保证。
useEffect保证如果相依性没有变更,就不会引发它。useMemo没有给予这种保证。
正如React文档中所述,您应该将useMemo视为纯粹的优化技术。即使您将useMemo替换为常规函数调用,您的程序也应该继续正常工作。
useEffect + useState可用于控制更新。甚至可用于打破循环依赖关系并防止无限更新循环。

nsc4cvqm

nsc4cvqm3#

我想说的是,除了异步特性之外,它们的设计方式可能会有一些不同。
useEffect是一个集合调用,无论是否异步,它都是在呈现所有组件之后收集的。
useMemo是一个本地调用,它只与这个组件有关,你可以把useMemo看作另一个赋值语句,它的优点是使用上次更新的赋值语句。
这意味着,useMemo更紧急,然后是useLayoutEffect,最后是useEffect

njthzxwz

njthzxwz4#

  • useEffect在UI呈现之后运行。但是,useMemo将在UI呈现之前计算值。
  • 比如useEffect与useLayoutEffect

相关问题