理解react hook中 useCallback 和 useMemo 的区别以及应用场景

理解react hook中useCallback和useMemo的区别以及应用场景

彻底理解 React hook useCallback和useMemo的区别

useCallback :

场景:
父组件中有状态 A 、状态 B ,函数 C(函数 C 中只使用到了状态 B) ,父组件需要将 函数 C 传递给子组件使用。
不使用 useCallback 的情况(子组件使用 memo() 函数进行优化):父组件中的状态 A 发生了改变,导致父组件重新渲染,虽然 子组件状态没有改变,使用到的 父组件传递过来的函数 C 也没有改变,但是子组件还是要同父组件一起重新渲染一次。

使用 useCallback 的情况(子组件使用 memo() 函数进行优化)

const 函数 C 的 memorize 版 = useCallback(() => {
     
	函数 C ();
}, [状态 B])

函数 C 的 memorize 版 传递给子组件,那么当父组件中的状态 A 发生了改变,导致父组件重新渲染时,由于子组件使用到的 函数 C 的 memorize 版 (函数的引用)并没有发生改变,所以子组件不会跟随父组件一起重新渲染一次。

memo() 函数的作用: 只有组件的 props 或者 state 发生改变时,shouldComponentUpdate 才会返回 true ,即组件才需要重新渲染。

大伙应该明白了useCallback的作用了,配合 memo 用于优化子组件的渲染次数。

useMemo

场景:
组件中有状态 A 、状态 B ,函数 C(函数 C 中只使用到了状态 B 进行计算) ,组件需要使用 函数 C 的返回值 D 进行页面渲染。
不使用 useMemo 的情况: 当组件的状态 A 改变(状态 C 并没有发生改变)时,由于组件需要重新渲染,所以会重新计算 D 值,也就是要重新执行一次 函数 C 的计算,但是实际上计算结果并没有发生改变,这从进行的重新计算是没有必要的。
如果函数 C 中计算 D 的计算量十分庞大的话,那么每次没有必要的重复计算是十分消耗性能的。我们期望,函数 C 只在其计算中使用到的状态数据发生改变时才进行重新计算。
使用 useMemo 的情况

  const memo 版本的 D = useMemo(() => 函数 C (B), [B]);
  function 函数 C (B) {
     
    console.log('函数 C 被执行');
    //比较大计算
    const array = new Array(B).fill(B);
    return array.reduce((currentTotal, item) => {
     
      return currentTotal + item;
    }, 0);
  }

memo 版本的 D 用于组件渲染,这样函数 C 并不会在每次组件渲染时都重新执行,只有在 函数 C 中使用到的状态发生改变的时候才会重新计算 D 的值。

不同之处

useCallback 优化针对于子组件的渲染(一般子组件使用 memo() 函数)
useMemo 优化针对于当前组件高开销的计算

补充 memo() 函数

const MyComponent = React.memo(function MyComponent(props) {
     
  /* 使用 props 渲染 */
});

React.memo 会在渲染之前检查 props 的变更,在 props 发生改变时才会重新渲染组件。但是
如果函数组件被 React.memo 包裹,且其实现中拥有 useState,useReducer 或 useContext 的 Hook,当 context 发生变化时,它仍会重新渲染。
默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。

function MyComponent(props) {
     
  /* 使用 props 渲染 */
}
function areEqual(prevProps, nextProps) {
     
  /*
  如果把 nextProps 传入 render 方法的返回结果与
  将 prevProps 传入 render 方法的返回结果一致则返回 true,
  否则返回 false
  */
}
export default React.memo(MyComponent, areEqual);

此方法仅作为性能优化的方式而存在。

React.memo()和PureComponent很相似,都是用来控制组件何时渲染的。我们都知道当组件props和state发生改变时,当前组件以及其子孙组件会重新渲染,但是有一些组件(纯文本组件)是不需要重新渲染的,这种不需要的组件被重新渲染会影响整体的渲染性能。

通过控制组件何时渲染可以帮助我们解决这个问题,在React中可以用来优化组件性能的方法大概有以下几种:

组件懒加载(React.lazy(...)和)
PureComponent
shouldComponentUpdate(...){...}生命周期函数
React.memo
与PureComponent不同的是,React.memo()是一个高阶组件,用于函数组件,通过对前后props进行浅比较,如果前后props不一致,该组件将重新渲染,反之,不进行渲染,使用缓存中的组件。

你可能感兴趣的:(React,react,hooks)