使用useMemo
(例如用于密集函数调用)而不是结合使用useEffect
和useState
有什么好处吗?
除了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
的一些实际示例是什么?
答案 0 :(得分:6)
useEffect
和setState
会在每次更改时导致额外的渲染:第一个渲染将与陈旧数据“滞后”,然后它将立即将新数据与另一个渲染排队。
假设我们有
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)
我认为在它们之间进行选择时,您应该考虑两个要点。
useEffect
在组件渲染后调用,因此您可以从中访问 DOM。例如,如果您想通过 refs 访问 DOM 元素,这很重要。
useEffect
保证在依赖项没有改变的情况下它不会被触发。 useMemo
不提供此类保证。
如 React documentation 中所述,您应该将 useMemo 视为纯粹的优化技术。即使您将 useMemo 替换为常规函数调用,您的程序也应该继续正常工作。
useEffect
+ useState
可用于控制更新。甚至打破循环依赖并防止无限更新循环。