[英]useMemo vs. useEffect + useState
使用useMemo
(例如用于密集函数调用)而不是使用useEffect
和useState
的组合有useEffect
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
改变时,两者都会计算结果, useMemo
的记忆在哪里开始?
useEffect
和setState
将在每次更改时导致额外的渲染:第一个渲染将“滞后”与陈旧数据,然后它将立即使用新数据排队附加渲染。
假设我们有:
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
。
我认为在它们之间进行选择时,您应该考虑两个要点。
useEffect
在组件渲染后调用,因此您可以从中访问 DOM。 例如,如果您想通过 refs 访问 DOM 元素,这很重要。
useEffect
保证在依赖项没有改变的情况下它不会被触发。 useMemo
不提供此类保证。
如React 文档中所述,您应该将 useMemo 视为纯优化技术。 即使您用常规函数调用替换 useMemo,您的程序也应该继续正常工作。
useEffect
+ useState
可用于控制更新。 甚至打破循环依赖并防止无限更新循环。
我想说除了异步性质之外,它们的设计方式可能存在一些差异。
useEffect
是一个集体调用,无论异步与否,它都是在所有组件渲染后收集的。
useMemo
是一个本地调用,它只与这个组件有关。 您可以将useMemo
视为另一个赋值语句,有时可以跳过赋值语句。
这意味着, useMemo
是更为迫切,然后useLayoutEffect
和最后被useEffect
,特别是当输入是来自一个道具。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.