React Hook中的性能优化:memo、useCallback、useMemo

一、概念

  React 性能优化的起因:

    在React中,默认情况下,当父组件重渲染时,子组件也会重渲染。

    在React中,子组件默认随父组件更新而更新。

  React 性能优化的方向:通过缓存,减少渲染次数、减少重复计算。

  React Hook性能优化的总结:memo缓存组件、useCallback缓存函数、useMemo缓存计算结果。

 

二、memo:使用React.memo高阶组件包裹子组件,当props不变时该子组件不会重新渲染。

import { memo } from "react";
function Child() {
   return <div>{Math.random()}</div>;
}
export default memo(Child);

 默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现:

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

 

三、useCallback:memo无法判断props中的函数是否改变。把回调函数和依赖项数组传入useCallback,返回该回调函数的memoized版本,当依赖项不变时该回调函数不会更新。

useCallback 要和 shouldComponentUpdate或React.memo 配套使用

子组件如果不用shouldComponentUpdate或React.memo,父组件更新时一定会更新

一般项目无需考虑性能优化,也就无需使用 useCallback,除非有个别非常复杂的组件,单独使用即可

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)

 应用于父组件把函数通过props传入子组件的场景。

当点击button1,Child重渲染;点击button2,Child没有重渲染。

import "./styles.css";
import { useCallback, useState, memo } from "react";
import Child from "./child";

export default function App() {
  const [count, setCount] = useState(false);
  const [count2, setCount2] = useState(false);

  const onClickChild = useCallback(() => {}, [count]);
  return (
    <div className="App">
      <Child onClick={onClickChild}></Child>
      <button
        onClick={() => {
          setCount(!count);
        }}
      >
        count:{count.toString()}
      </button>
      <button
        onClick={() => {
          setCount2(!count2);
        }}
      >
        count2:{count2.toString()}
      </button>
    </div>
  );
}

 

四、useMemo:把回调函数和依赖项数组传入useMemo,返回该回调函数返回值的memoized版本,当依赖项不变时该返回值不会重新计算。

应用于需要避免多次渲染时的重复计算的场景。

当a和b不变时,computeExpensiveValue(a, b)的返回值不会重新计算。

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

 

posted @ 2021-09-30 16:39  starlog  阅读(801)  评论(0)    收藏  举报