React如何使用memo、useMemo、useCallBack?

211 阅读2分钟

React.memo的作用是什么?

简单来讲,就是父组件的state发生变化后,父组件本身(函数式组件)会重新执行一遍,其子组件也会重新执行一遍

父组件

  // 父组件里定义了一个count计数器
  const [count, setCount] = useState(0);

  return (
    <>
      {/* 父组件里每次点击按钮,count都会 + 1 */}
      <button onClick={() => setCount(count + 1)}>加1</button>
      {/* 纯UI组件,又称傻瓜组件,哈哈哈 */}
      <Test />
    </>
  );

然后Test组件内部:

function Test(props:any) {
  console.log('我执行了');

  return <button>UI</button>
}

export default Test

可以看到,每次点击按钮,控制台都会打印一次我执行了

image.png

如果在Test组件内部使用memo,那么我执行了这句话只会打印一次。

// export default Test
export default React.memo(Test)

可是在实际中,很少会用到傻瓜组件,就以这个Test组件为例,还可能接收一些props参数。当props改变时,子组件毫无疑问会重新渲染。如果继续使用React.memo,它会判断新的props和旧的props是否相同,如果相同就不会执行子组件函数,否者会再次执行。

比如下面这种Test组件就不会重新渲染:

<Test suibian={1}  />

再下面这种就会重新渲染:

<Test suibian={{a: 1}}  />

总结来说,memo的作用就是当props发生改变时,组件才会重新渲染,否则使用缓存的渲染结果。

useMemo的作用是什么?

字面意思,就是使用缓存。

看下面父组件里的代码,当我们只是改变count的值时,name没有变,但Test组件依旧会重新渲染。

  const [count, setCount] = useState(0);
  const [name, setName] = useState('joy')

  const data = {
    name
  }

  return (
    <>
      <button onClick={() => setCount(count + 1)}>加1</button>
      <Test suibian={data}  />
    </>
  );

使用useMemo,即使count改变Test组件也只会渲染一次了。

  const data = useMemo(() => {
    return {
      name
    }
  }, [name])

这里可能会有人好奇了,如果第二个参数是空数组或者不传会怎么样?

若是空数组,即使count改变,data永远都是第一次初始的值。

若是不传,那么useMemo就相当于没使用一样,没起到任何缓存效果。

还有一种情况,若第二个参数传的是表达式,会怎么样呢?

  const data = useMemo(() => {
    return {
      name
    }
  }, [5 === count])

会在count === 5的时候,data会刷新一般,然后Test组件又重新渲染了。

总结来说,useMemo就是只有第二个参数发生改变时才会重新执行回调。

useCallBack的作用是什么?

它就是useMemo的语法糖,第一个参数只能是函数类型。

  const goFn = useCallback(() => {
    console.log(name);
  }, [name])

最后

还得在实际中多运用,才能游刃有余,代码写得越来越顺畅,别人的代码也能看懂了。