useCallback和useMemo 都是React中用于优化缓存的Hooks。
React基础的缓存处理是通过一种浅比较的技术来实现的,通过判断前后state和prop是否发生变化来减少组件的渲染,然而这种方式是通过对比state和prop的引用而非值来进行处理的,这就会造成在一些值未改变,但重新分配空间的情况下,额外增加了许多不必要的渲染。例如,在某些父组件state变化时,子组件不论是否调用变化的state都会重新渲染。
useMemo 可以帮助减少这种额外渲染,通过设定相关依赖,只要依赖不变,就不进行重复的渲染操作。useCallback 与其类似,差别在于它可以处理函数。
1、使用useMemo缓存计算结果:
function ExampleComponent() {
const \[count, setCount] = useState(0);
// 使用 useMemo 缓存计算结果,避免在每次渲染时重复计算
const doubledCount = useMemo(() => {
console.log('Calculating doubled count...');
return count \* 2;
}, \[count]);
return ( <div> <p>Count: {count}</p> <p>Doubled Count: {doubledCount}</p>
\<button onClick={() => setCount(count + 1)}>增加</button> </div>
);
}
\
useCallback 的源码实际上就是调用 useMemo 并返回 memoized 值。
function useCallback(callback, deps) {
return useMemo(() => callback, deps);
}
2、使用useCallback优化事件处理函数:
function ExampleComponent() {
const \[count, setCount] = useState(0);
// 使用 useCallback 优化事件处理函数,避免在每次渲染时创建新的函数
const handleClick = useCallback(() => {
setCount(count + 1);
}, \[count]);
return ( <div> <p>Count: {count}</p> <button onClick={handleClick}>增加</button> </div>
);
}
useMemo 的源码:
useMemo(create, deps) {
// 检查 deps 是否变化,如果没变化直接返回缓存值
if (this.memoizedState\[create] !== null && all(equal(deps, this.memoizedState\[create]\[1]))) {
return this.memoizedState\[create]\[0];
}
// 调用 create() 计算新值
var value = create();
// 更新缓存
this.memoizedState\[create] = \[value, deps];
// 返回新值
return value;
}
它会先检查缓存中是否有 memoized 值以及 deps 是否发生变化。如果没有变化,直接返回缓存值。如果 deps 变化,调用 create() 计算新值,更新缓存并返回。所以总体来说,useMemo 的作用是通过记忆化避免在每个渲染周期中执行创建函数以计算值,它只会在依赖发生变化时重新计算,并返回最新的值。
参考: