[英]useMemo vs. useEffect + useState
Are there any benefits in using useMemo
(eg for an intensive function call) instead of using a combination of useEffect
and useState
?使用
useMemo
(例如用于密集函数调用)而不是使用useEffect
和useState
的组合有useEffect
useState
?
Here are two custom hooks that work exactly the same on first sight, besides useMemo
's return value being null
on the first render:这里有两个自定义钩子,乍一看完全相同,除了
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]);
};
Both calculate the result each time their parameter someNumber
changes, where is the memoization of useMemo
kicking in?每次他们的参数
someNumber
改变时,两者都会计算结果, useMemo
的记忆在哪里开始?
The useEffect
and setState
will cause extra renders on every change: the first render will "lag behind" with stale data and then it'll immediately queue up an additional render with the new data. useEffect
和setState
将在每次更改时导致额外的渲染:第一个渲染将“滞后”与陈旧数据,然后它将立即使用新数据排队附加渲染。
Suppose we have:假设我们有:
function expensiveCalculation(x) { return x + 1; }; // Maybe I'm running this on a literal potato
Lets suppose someNumber
is initially 0:让我们假设
someNumber
最初是 0:
useMemo
version immediately renders 1
. useMemo
版本立即呈现1
。useEffect
version renders null
, then after the component renders the effect runs, changes the state, and queues up a new render with 1
. useEffect
版本渲染null
,然后在组件渲染效果后运行,更改状态,并使用1
将新渲染排队。 Then if we change someNumber
to 2:然后,如果我们将
someNumber
更改为 2:
useMemo
runs and 3
is rendered. useMemo
运行并呈现3
。useEffect
version runs, and renders 1
again, then the effect triggers and the component reruns with the correct value of 3
. useEffect
版本运行,并再次渲染1
,然后触发效果并且组件以正确的3
值重新运行。 In terms of how often expensiveCalculation
runs, the two have identical behavior, but the useEffect
version is causing twice as much rendering which is bad for performance for other reasons.就
expensiveCalculation
运行的频率而言,两者具有相同的行为,但useEffect
版本导致两倍的渲染,这对性能不利,因为其他原因。
Plus, the useMemo
version is just cleaner and more readable, IMO.另外,IMO 的
useMemo
版本更清晰、更易读。 It doesn't introduce unnecessary mutable state and has fewer moving parts.它不会引入不必要的可变状态并且具有更少的移动部件。
So you're better off just using useMemo
here.所以你最好在这里使用
useMemo
。
I think there are two main points you should consider when choosing between them.我认为在它们之间进行选择时,您应该考虑两个要点。
useEffect
called after component has been rendered, so you can access DOM from it. useEffect
在组件渲染后调用,因此您可以从中访问 DOM。 For example, this is important if you want to access DOM elements via refs.例如,如果您想通过 refs 访问 DOM 元素,这很重要。
useEffect
guarantees that it will not be fired if dependencies have not changed. useEffect
保证在依赖项没有改变的情况下它不会被触发。 useMemo
does not give such guarantees. useMemo
不提供此类保证。
As stated in the React documentation , you should consider useMemo as pure optimization technique.如React 文档中所述,您应该将 useMemo 视为纯优化技术。 Your program should continue to work correctly even if you replace useMemo with regular function call.
即使您用常规函数调用替换 useMemo,您的程序也应该继续正常工作。
useEffect
+ useState
can be used to control updates. useEffect
+ useState
可用于控制更新。 Even to break-up circular dependencies and prevent infinite update loops.甚至打破循环依赖并防止无限更新循环。
I would say other than the async nature, there might be some difference in terms how they are designed.我想说除了异步性质之外,它们的设计方式可能存在一些差异。
useEffect
is a collective call, async or not, it's collected after all components are rendered. useEffect
是一个集体调用,无论异步与否,它都是在所有组件渲染后收集的。
useMemo
is a local call, it only have something to do with this component. useMemo
是一个本地调用,它只与这个组件有关。 You could just think of useMemo
as another assignment statement with benefits to skip assignment sometimes.您可以将
useMemo
视为另一个赋值语句,有时可以跳过赋值语句。
Which means, useMemo
is more urgent, then useLayoutEffect
and the last being useEffect
, especially when the input is from a prop.这意味着,
useMemo
是更为迫切,然后useLayoutEffect
和最后被useEffect
,特别是当输入是来自一个道具。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.