coderliush / Blog

博客
0 stars 0 forks source link

react 系列之 React.memo, useMemo, useCallback #9

Open coderliush opened 3 years ago

coderliush commented 3 years ago

React.memo

React.memo 类似于 class 组件的 pureComponent。对函数组件来说,父组件 render,即使 props 没有改变,子组件也会重新 render。 React.memo 默认对 props 进行浅比较。控制对比过程,传入一个函数。与 class 组件不同的是,areEqual 返回 true 不渲染,areEqual 返回 false 重新渲染。

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

useMemo useCallback

useMemo 和 useCallback 第一次参数都是一个函数,第二个参数是依赖项。 useMemo 执行 fn,返回一个 memoized 值。 useCallback 不执行 fn,返回一个 memoized 回调函数。

const memoizedValue = useMemo(fn, [a, b]);

const memoizedCallback = useCallback(fn, [a, b]);

useCallback 使用场景

子组件 props 接收一个函数 fn,每次父组件 render 的时候,fn 都会重新创建,所以每次子组件也会重新 render。此时使用 useCallback 解决这个问题

before

const APP = () => {
  const fn = () => {
    // do something
  }

  return (
    <>
      <Child onClick={fn}>child</Child>
    </>
  )
}

after

const APP = () => {
  const fn = React.useCallback(() => {
    // do something
  }, [])

  return (
    <>
      <Child onClick={fn}>child</Child>
    </>
  )
}

useMemo 使用场景

组件加载时先执行函数。每次加载组件,函数都会执行,即使是没有必要的。

before

const App = (props) => {
  const text = () => {
    // compute expensive 
    fn(props.string)
  }

  return <p>{text}</p>
}

after

const App = (props) => {
  const fn = React.useMemo(() => {
    // compute expensive
    fn(props.string)
  }, [props.string])
}