useMemo与useEffect + useState

时间:2019-05-07 18:58:01

标签: javascript reactjs typescript react-hooks

使用useMemo(例如用于密集函数调用)而不是结合使用useEffectuseState有什么好处吗?

除了useMemo在第一个渲染器上的返回值为null以外,还有两个自定义挂钩在乍看之下完全相同:

  

useEffect和useState

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

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

  return result;
};
  

useMemo

const useCalculateWithMemo = numberProp => {
  return useMemo(() => {
    return expensiveCalculation(numberProp);
  }, [numberProp]);
};

https://codesandbox.io/s/nkxolxwzkj

两者都计算每次“ prop”更改时,useMemo的“缓存”在哪里?

useMemo的一些实际示例是什么?

2 个答案:

答案 0 :(得分:6)

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


假设我们有

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

让我们假设numberProp最初为0:

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

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

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

expensiveCalculation的运行频率而言,两者的行为相同,但是useEffect版本的渲染量是原来的两倍,这由于其他原因而对性能不利。

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

因此,最好在这里使用useMemo

答案 1 :(得分:0)

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

  1. 函数调用的时间。

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

  1. 语义保证。

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

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

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