使用React.memo,useCallback和React.useMemo来优化渲染

在渲染优化中使用memo、useCallback和React.useMemo进行优化。

在React开发中,可以通过在开发过程中注意重新渲染的问题来提高性能。为了控制重新渲染,可以使用缓存技术,包括React.memo、useCallback和React.useMemo。

备忘录类型

通过对React进行记忆化,可以控制和优化重新渲染。
记忆化是通过保留上次的处理结果来加快处理速度。

種類対象React.memoコンポーネントuseCallbackコールバック関数React.useMemo変数

再渲染发生的条件。

    1. 被 State 更新的组件

 

    1. 被 Prop 更新的组件

 

    被重新渲染的组件下的所有组件

让我们尝试重新渲染

import ReactDom from "react-dom";
import { App } from "./App";

ReactDom.render(<App />, document.getElementById("root"));
);

import { useState, useCallback } from "react";
import { Child1 } from "./components/Child1";
import { Child4 } from "./components/Child4";

export const App = () => {
  console.log("App レンダリング ");

  const [num, setNum] = useState(0);

  const onClickButton = () => {
    setNum(num + 1);
  };

  const onClickReset = useCallback(() => {
    setNum(0);
  }, []);

  return (
    <>
      <button onClick={onClickButton}>ボタン</button>
      <p>{num}</p>
      <Child1 onClickReset={onClickReset} />
      <Child4 />
    </>
  );
};
import { Child2 } from "./Child2";
import { Child3 } from "./Child3";

const style = {
  backgroundColor: "#AAFFFF ",
};

export const Child1 = (props) => {
  console.log("Child1 レンダリング ");

  const { onClickReset } = props;

  return (
    <div style={style}>
      <p>Child1</p>
      <button onClick={onClickReset}>リセット</button>
      <Child2 />
      <Child3 />
    </div>
  );
};

const style = {
  backgroundColor: "#FFCCFF",
};

export const Child2 = () => {
  console.log("Child2 レンダリング ");

  return (
    <div style={style}>
      <p>Child2</p>
    </div>
  );
};
const style = {
  backgroundColor: "#FFCCFF",
};

export const Child3 = () => {
  console.log("Child3 レンダリング ");

  return (
    <div style={style}>
      <p>Child3</p>
    </div>
  );
};
const style = {
  backgroundColor: "#66FF00",
};

export const Child4 = () => {
  console.log("Child4 レンダリング ");

  return (
    <div style={style}>
      <p>Child4</p>
    </div>
  );
};
FireShot Capture 085 - React App - localhost.png

在上述代码执行之后,当你按下计数按钮时,你可以确认所有组件都被重新渲染了,效果如下。

スクリーンショット 2021-09-30 23.38.25.png

使用React.memo来对组件进行记忆化

React.memo是用来记忆组件的。将上面代码中的组件改为使用React.memo。

const Component = memo(() =>{});
import { useState, memo, useCallback } from "react";
import { Child1 } from "./components/Child1";
import { Child4 } from "./components/Child4";

export const App = memo(() => { // memoに変更した
  console.log("App レンダリング ");

  const [num, setNum] = useState(0);

  const onClickButton = () => {
    setNum(num + 1);
  };

  const onClickReset = useCallback(() => {
    setNum(0);
  }, []);

  return (
    <>
      <button onClick={onClickButton}>ボタン</button>
      <p>{num}</p>
      <Child1 onClickReset={onClickReset} />
      <Child4 />
    </>
  );
});
import { memo } from "react";
import { Child2 } from "./Child2";
import { Child3 } from "./Child3";

const style = {
  backgroundColor: "#AAFFFF ",
};

export const Child1 = memo((props) => { // memoに変更した
  console.log("Child1 レンダリング ");

  const { onClickReset } = props;

  return (
    <div style={style}>
      <p>Child1</p>
      <button onClick={onClickReset}>リセット</button>
      <Child2 />
      <Child3 />
    </div>
  );
});

import { memo } from "react";

const style = {
  backgroundColor: "#FFCCFF",
};

export const Child2 = memo(() => { // memoに変更した
  console.log("Child2 レンダリング ");

  return (
    <div style={style}>
      <p>Child2</p>
    </div>
  );
});
import { memo } from "react";

const style = {
  backgroundColor: "#FFCCFF",
};

export const Child3 = memo(() => { // memoに変更した
  console.log("Child3 レンダリング ");

  return (
    <div style={style}>
      <p>Child3</p>
    </div>
  );
});
import { memo } from "react";

const style = {
  backgroundColor: "#66FF00",
};

export const Child4 = memo(() => {
  console.log("Child4 レンダリング ");

  return (
    <div style={style}>
      <p>Child4</p>
    </div>
  );
});
FireShot Capture 086 - React App - localhost.png

通过记忆化,我们可以确认只有App组件重新渲染了。

スクリーンショット 2021-10-01 0.03.14.png

尝试通过函数进行再渲染。

我写了一个函数来重置计数按钮,并创建了将函数传递给Child1的代码。当执行计数增加时,会导致Child1重新渲染,这就是之前记忆化的问题。

FireShot Capture 087 - React App - localhost.png
スクリーンショット 2021-10-01 23.46.59.png
import { useState, memo } from "react";
import { Child1 } from "./components/Child1";
import { Child4 } from "./components/Child4";

export const App = memo(() => {
  console.log("App レンダリング ");

  const [num, setNum] = useState(0);

  const onClickButton = () => {
    setNum(num + 1);
  };

// 追加しました
  const onClickReset = () => {
    setNum(0);
  };

  return (
    <>
      <button onClick={onClickButton}>ボタン</button>
      <p>{num}</p>
      <Child1 onClickReset={onClickReset} /> // 関数の受け渡しを追加しました
      <Child4 />
    </>
  );
});

import { memo } from "react";
import { Child2 } from "./Child2";
import { Child3 } from "./Child3";

const style = {
  backgroundColor: "#AAFFFF ",
};

export const Child1 = memo((props) => {
  console.log("Child1 レンダリング ");

  const { onClickReset } = props;

  return (
    <div style={style}>
      <p>Child1</p>
      <button onClick={onClickReset}>リセット</button>
      <Child2 />
      <Child3 />
    </div>
  );
});

尝试使用useCallback进行函数记忆化

React中的memoization函数使用useCallback。将onClickReset函数使用useCallback如下方式编写。将函数作为第一个参数,将依赖数组的元素作为第二个参数写入。当依赖数组为空时,它只会被加载和渲染一次。从第二次开始,将使用最初创建的内容。

import { useState, memo, useCallback } from "react";
import { Child1 } from "./components/Child1";
import { Child4 } from "./components/Child4";

export const App = memo(() => {
  console.log("App レンダリング ");

  const [num, setNum] = useState(0);

  const onClickButton = () => {
    setNum(num + 1);
  };

  const onClickReset = useCallback(() => { //useCallbackを使うように変更した
    setNum(0);
  }, []);

  return (
    <>
      <button onClick={onClickButton}>ボタン</button>
      <p>{num}</p>
      <Child1 onClickReset={onClickReset} />
      <Child4 />
    </>
  );
});

Child1 不再重新渲染。

スクリーンショット 2021-10-01 23.59.00.png

在React中可以使用React.useMemo来进行变量的记忆化。

要实现变量和值的记忆化,我们可以使用React的useMemo函数。第一个参数传入计算式,第二个参数传入依赖数组的元素。只有依赖数组的元素发生变化时,才会重新计算记忆化的值。在下面的代码中,如果a和b的值不变,那么将重复使用首次渲染时的值。

const memoizedValue = useMemo(() => {
    return a + b;
    }, [a, b]);
广告
将在 10 秒后关闭
bannerAds