使用useMemo
(例如,对于密集的函数调用)而不是使用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
的记忆在哪里起作用?
4条答案
按热度按时间gg58donl1#
useEffect
和setState
将在每次更改时导致额外渲染:第一个渲染将“落后”于过时的数据,然后它将立即使用新的数据排队另外一个渲染。假设我们有:
假设
x
最初为0:useMemo
版本会立即呈现1
。useEffect
版本渲染null
,然后在组件渲染效果后运行,更改状态,并使用1
将新渲染排队。然后,如果我们将
x
更改为2:useMemo
并渲染3
。useEffect
版本运行,并再次渲染1
,然后效果触发,组件使用正确的值3
重新运行。就
expensiveCalculation
的运行频率而言,这两个版本的行为完全相同,但useEffect
版本导致的渲染量是expensiveCalculation
版本的两倍,由于其他原因,这对性能不利。另外,
useMemo
版本更干净,可读性更强,IMO。它没有引入不必要的可变状态,移动部件更少。所以最好在这里使用
useMemo
。cuxqih212#
我认为在两者之间进行选择时,有两个要点你应该考虑。
1.调用函数时间
useEffect
在呈现组件后调用,因此您可以从该组件访问DOM例如,如果您希望通过引用访问DOM元素,这一点很重要1.语义保证。
useEffect
保证如果相依性没有变更,就不会引发它。useMemo
没有给予这种保证。正如React文档中所述,您应该将useMemo视为纯粹的优化技术。即使您将useMemo替换为常规函数调用,您的程序也应该继续正常工作。
useEffect
+useState
可用于控制更新。甚至可用于打破循环依赖关系并防止无限更新循环。nsc4cvqm3#
我想说的是,除了异步特性之外,它们的设计方式可能会有一些不同。
useEffect
是一个集合调用,无论是否异步,它都是在呈现所有组件之后收集的。useMemo
是一个本地调用,它只与这个组件有关,你可以把useMemo
看作另一个赋值语句,它的优点是使用上次更新的赋值语句。这意味着,
useMemo
更紧急,然后是useLayoutEffect
,最后是useEffect
。njthzxwz4#