React · 揭秘 useMemo & useCallback 的妙用,掌握 Hooks 的精髓
2023-11-26 02:48:02
前言
默认情况下,父组件的状态 (state) 发生变化时,不仅会重新渲染自己,还会重新渲染其子组件。这种情况在一些场景下可能会导致性能问题,特别是当子组件很复杂或计算量很大时。为了解决这个问题,React 发明了 useMemo 和 useCallback 来帮助你减少不必要的渲染。
一、useMemo 详解
useMemo 允许你在函数组件中缓存一个值,该值只会在其依赖项发生变化时才重新计算。这对于一些计算量很大的函数非常有用,可以显著提升性能。
1. 语法
const memoizedValue = useMemo(() => expensiveComputation(props), [props]);
其中:
expensiveComputation
是一个纯函数,它会返回一个值。props
是 memoizedValue 依赖的 props。
2. 原理
useMemo 会在组件首次渲染时调用 expensiveComputation 函数,并将结果存储在 memoizedValue 中。在随后的渲染中,useMemo 会比较 memoizedValue 的依赖项 (props) 是否发生变化。如果依赖项没有变化,useMemo 就会直接返回 memoizedValue,而不会重新调用 expensiveComputation 函数。
3. 使用场景
useMemo 可以用于以下场景:
- 缓存一些计算量很大的值,例如一个复杂的函数或一个大型数组的过滤结果。
- 缓存一些需要从外部 API 获取的数据,例如用户数据或产品列表。
- 缓存一些需要进行复杂计算的组件的子树,例如一个带有复杂逻辑的表单。
二、useCallback 详解
useCallback 允许你在函数组件中缓存一个函数,该函数只会在其依赖项发生变化时才重新创建。这对于一些需要在组件中多次调用的函数非常有用,可以减少不必要的函数创建,并提升性能。
1. 语法
const memoizedCallback = useCallback(() => {
// Do something
}, [props]);
其中:
memoizedCallback
是一个 memoized 的回调函数。props
是 memoizedCallback 依赖的 props。
2. 原理
useCallback 会在组件首次渲染时创建一个 memoizedCallback 函数,并将它存储在内存中。在随后的渲染中,useCallback 会比较 memoizedCallback 的依赖项 (props) 是否发生变化。如果依赖项没有变化,useCallback 就会直接返回 memoizedCallback,而不会重新创建它。
3. 使用场景
useCallback 可以用于以下场景:
- 缓存一些需要在组件中多次调用的函数,例如一个事件处理函数或一个计时器函数。
- 缓存一些需要传递给子组件的函数,例如一个更新子组件状态的函数或一个控制子组件行为的函数。
- 缓存一些需要在组件中多次调用的复杂逻辑,例如一个表单验证函数或一个数据处理函数。
三、useMemo 与 useCallback 的区别
useMemo 和 useCallback 都是 React 提供的 Hooks,它们都用于优化组件的性能。但它们之间还是有一些区别的:
- useMemo 用于缓存一个值,而 useCallback 用于缓存一个函数。
- useMemo 只会在其依赖项发生变化时重新计算,而 useCallback 只会在其依赖项发生变化时重新创建。
- useMemo 通常用于缓存一些计算量很大的值,而 useCallback 通常用于缓存一些需要在组件中多次调用的函数。
四、总结
useMemo 和 useCallback 是 React 中非常有用的两个 Hooks,它们可以帮助你减少不必要的渲染和函数创建,从而提升组件的性能。在使用它们时,需要注意以下几点:
- useMemo 和 useCallback 只能在函数组件中使用。
- useMemo 和 useCallback 都是纯函数,这意味着它们不会修改组件的状态或产生副作用。
- useMemo 和 useCallback 可以嵌套使用。
- useMemo 和 useCallback 可以与其他 Hooks 一起使用,例如 useEffect 和 useState。