Skip to content

React 如何使用 memo、useMemo、useCallBack?

React.memo 的作用是什么?

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

父组件

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

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

然后 Test 组件内部:

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

  return <button>UI</button>
}

export default Test

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

image.png

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

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

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

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

js
<Test suibian={1}  />

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

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

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

useMemo 的作用是什么?

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

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

js
  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 组件也只会渲染一次了。

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

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

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

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

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

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

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

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

useCallBack 的作用是什么?

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

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

最后

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

Released under the MIT License.