既然标题里提到了‘缓存’, 不难想象useMemo这个钩子函数跟性能优化有关系。大家试想一下下面的场景,组件里有两个状态值 number1 和 number2. 按需求,当number1发生变化的时候需要触发fn方法执行计算。 那么当number2发生变化的时候fn方法会被执行么?很显然也是会被触发的。
示例代码:
import { useMemo, useState } from "react";
function fn(n: number): number {
console.log('fn func is executing...');
let sum = 0;
for(let i=1; i <= n; i++) {
sum += i;
}
return sum;
}
function UseMemo() {
const [number1, setNumber1] = useState(0);
const [number2, setNumber2] = useState(0);
const result = fn(number1);
console.log('component is rendering...')
return (
<div>
useMemo example
<div>
<p>number1: {number1}</p>
<button onClick={() => setNumber1(number1 + 1)}>change number1</button>
</div>
<div>
<p>number2: {number2}</p>
<button onClick={() => setNumber2(number2 + 1)}>change number2</button>
</div>
<div>
{result}
</div>
</div>
);
}
export default UseMemo;
执行效果:
点击button ‘change number1’, 从运行结果可以看出, fn 方法被执行了, 符合我们的期待
这回我clear console, 然后点击button ‘change number2’, 从运行结果可以看出, fn方法也被执行了。但是我们fn方法只跟number1相关, number2变化的时候也触发了fn方法, 显然存在资源浪费。
解决方法:useMemo 登场,只有当number1值发生变化的时候才会触发fn方法,并缓存计算结果。
import { useMemo, useState } from "react";
function fn(n: number): number {
console.log('fn func is executing...');
let sum = 0;
for(let i=1; i <= n; i++) {
sum += i;
}
return sum;
}
function UseMemo() {
const [number1, setNumber1] = useState(0);
const [number2, setNumber2] = useState(0);
// const result = fn(number1);
const result = useMemo(() => {
return fn(number1);
}, [number1]);
console.log('component is rendering...')
return (
<div>
useMemo example
<div>
<p>number1: {number1}</p>
<button onClick={() => setNumber1(number1 + 1)}>change number1</button>
</div>
<div>
<p>number2: {number2}</p>
<button onClick={() => setNumber2(number2 + 1)}>change number2</button>
</div>
<div>
{result}
</div>
</div>
);
}
export default UseMemo;
执行结果:
可以看出,这回当点击button‘change number2’ 的时候, fn方法并没有触发 >_<