返回

用useMemo和useCallback优化React无用渲染的性能问题

前端







## 前言React中,可以使用useMemo和useCallback来优化无用渲染的性能问题。本文是自己学习useMemo和useCallback的笔记,介绍了它们的原理和使用场景。

## useMemo

### 原理
useMemo的作用是将一个函数的结果缓存起来,如果这个函数的入参没有发生变化,那么在组件重新渲染时,就不会重新执行这个函数,而是直接使用缓存的结果。这可以有效地减少组件的重新渲染次数,从而提高组件的性能。

### 使用场景
useMemo的典型使用场景是,当一个组件需要在每次渲染时执行一个计算量很大的函数时,可以使用useMemo将这个函数的结果缓存起来。这样,在组件重新渲染时,就可以直接使用缓存的结果,而无需重新执行这个函数。

举个例子,假设有一个组件需要在每次渲染时计算一个数组的长度。我们可以使用useMemo将这个数组的长度缓存起来,这样,在组件重新渲染时,就可以直接使用缓存的结果,而无需重新计算数组的长度。

```javascript
const MyComponent = () => {
  const array = [1, 2, 3, 4, 5];

  // 使用useMemo将数组的长度缓存起来
  const length = useMemo(() => {
    return array.length;
  }, [array]);

  return (
    <div>
      数组的长度:{length}
    </div>
  );
};

useCallback

原理

useCallback的作用是将一个函数包裹成一个新的函数,如果这个新的函数的入参没有发生变化,那么在组件重新渲染时,这个新的函数就不会重新生成。这可以有效地减少组件的重新渲染次数,从而提高组件的性能。

使用场景

useCallback的典型使用场景是,当一个组件需要在每次渲染时向子组件传递一个回调函数时,可以使用useCallback将这个回调函数包裹成一个新的函数。这样,在组件重新渲染时,子组件就不会重新接收这个回调函数,而是直接使用缓存的结果。

举个例子,假设有一个父组件需要向子组件传递一个回调函数,这个回调函数需要在子组件中执行一个计算量很大的操作。我们可以使用useCallback将这个回调函数包裹成一个新的函数,这样,在父组件重新渲染时,子组件就不会重新接收这个回调函数,而是直接使用缓存的结果。

const ParentComponent = () => {
  const handleClick = () => {
    // 执行一个计算量很大的操作
  };

  // 使用useCallback将回调函数包裹成一个新的函数
  const memoizedHandleClick = useCallback(handleClick, []);

  return (
    <div>
      <ChildComponent onClick={memoizedHandleClick} />
    </div>
  );
};

const ChildComponent = ({ onClick }) => {
  return (
    <button onClick={onClick}>
      点击我
    </button>
  );
};

区别

useMemo和useCallback都是用来优化React组件性能的钩子,但是它们的作用并不相同。useMemo用于缓存一个函数的结果,而useCallback用于缓存一个函数本身。

useMemo的入参是一个函数和一个依赖数组,如果依赖数组中的任何一个值发生变化,那么useMemo就会重新执行这个函数。useCallback的入参是一个函数和一个依赖数组,如果依赖数组中的任何一个值发生变化,那么useCallback就会重新生成一个新的函数。

总结

useMemo和useCallback都是非常有用的钩子,可以用来优化React组件的性能。在使用它们之前,需要先了解它们的原理和使用场景,这样才能正确地使用它们。