使用useMemo
(例如,对于密集型函数调用)而不是使用use效应
和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
改变时,都会计算结果,usemo
的记忆在哪里?
useffect
和setState
将在每次更改时导致额外的渲染:第一次渲染将使用陈旧数据“滞后”,然后它将立即使用新数据排队进行额外渲染。
假设我们有:
function expensiveCalculation(x) { return x + 1; }; // Maybe I'm running this on a literal potato
假设someNumber
最初为0:
useMemo
版本立即呈现1
。null
,然后在组件呈现效果后运行,更改状态,并用1
排队新呈现。然后,如果我们将某些数字
更改为2:
usemo
并呈现3
李> useffect
版本运行,并再次呈现1
,然后效果触发,组件以正确的3
值重新运行李>就忙乱计算
的运行频率而言,两者具有相同的行为,但是use效应
版本会导致两倍的渲染,这对其他原因的性能不利。
另外,IMO的useMemo
版本更干净、可读性更强。它不会引入不必要的可变状态,并且运动部件更少。
因此,您最好在此处使用usemo
。
我认为在选择它们之间应该考虑两个要点。
useffect
在呈现组件后调用,所以您可以从中访问DOM。例如,如果希望通过引用访问DOM元素,这一点很重要。
useffect
保证在依赖项未更改时不会触发它<代码>使用备忘录不提供此类保证。
正如RealDebug文档中所述,您应该将USEEMO视为纯粹的优化技术。即使用常规函数调用替换UseMoom,您的程序也应该继续正常工作。
useffect
useState
可用于控制更新。甚至可以打破循环依赖,防止无限更新循环。
我想说的是,除了异步特性之外,它们的设计方式可能会有所不同。
无论是否异步,它都是在呈现所有组件后收集的。
useMemo
是一个本地调用,它只与此组件有关。您可以将useMemo
视为另一个赋值语句,它具有使用上次更新赋值的好处。
这意味着,usemo
更紧急,然后是useLayoutEffect
,最后一个是useffect
。