每天对自己多问几个为什么,总是有着想象不到的收获。 一个菜鸟小白的成长之路(copyer)
目的:
useCallback
和 useMemo
是react的hooks中的两个函数,专门用于性能优化
的。
执行时机:
useCallback 和 useMemo 在第一次渲染组件的时候,就会执行,拿到各自的缓存;
之后,当它们的依赖发生改变的时候,才会执行。
useCallback缓存的是函数
useMemo缓存的是值
useMemo的使用场景
function Example() {
const [count, setCount] = useState(1);
const [val, setValue] = useState('');
// 不好的写法
// function calc() {
// console.log('calc函数执行');
// let sum = 0;
// for (let i = 0; i < count * 100; i++) {
// sum += i;
// }
// return sum;
// }
//正确的写法
const calc = useMemo(() => {
console.log('calc函数执行');
let sum = 0;
for (let i = 0; i < count * 100; i++) {
sum += i;
}
return sum;
}, [count])
return <div>
<h4>{count}-{val}</h4>
<h4>{calc}</h4>
<div>
<button onClick={() => setCount(count + 1)}>+c1</button>
<input value={val} onChange={event => setValue(event.target.value)}/>
</div>
</div>
}
针对于上面错误的写法: 无论是count改变,还是 val 改变,都会执行 calc 函数的执行。看calc的代码,只有count发生变化,才会对渲染有不同的结果;那么对于 val 变化时,执行 calc 函数就是没有必要的,所以需要优化下。
那么上面好的写法: 就是使用useMemo
这个函数,第一次渲染的时候,就缓存了计算值,并且只有当count发生变化的时候,才会重新执行useMemo这个函数,也就也意味着 val的变化,也是不会执行useMemo包裹的函数。
useCallback的使用场景
性能问题:
没有加useCallback的时候
function App() {
const [val, setVal] = useState("");
const onChange = (evt) => {
setVal(evt.target.value);
};
return <input val={val} onChange={onChange} />;
}
加上useCallback的时候
const onChange = useCallback(evt => {
setVal(evt.target.value);
}, []);
//这样的效果可能更差 等价于
const temp = evt => {
setVal(evt.target.value);
};
const onChange = useCallback(temp, []); //useCallback需要额外的开销
两者之间的比较:
useMemo和useCallback都是reactHook提供的两个API,用于缓存数据,优化性能;两者接收的参数都是一样的,第一个参数表示一个回调函数,第二个表示依赖的数据。
共同作用
在依赖数据发生变化的时候,才会调用传进去的回调函数去重新计算结果,起到一个缓存的作用
两者的区别
useMemo
缓存的结果是回调函数中return回来的值,主要用于缓存计算结果的值,应用场景如需要计算的状态
useCallback
缓存的结果是函数,主要用于缓存函数,应用场景如需要缓存的函数,因为函数式组件每次任何一个state发生变化,会触发整个组件更新,一些函数是没有必要更新的,此时就应该缓存起来,提高性能,减少对资源的浪费;另外还需要注意的是,useCallback应该和React.memo配套使用,缺了一个都可能导致性能不升反而下降。
参考资料:
useMemo与useCallback使用指南_大灰狼的小绵羊哥哥的博客
useMemo和useCallback的区别及使用场景_GodLoveMe的博客
https://blog.csdn.net/qq_35770417/article/details/110000491