使用React.memo,useCallback和React.useMemo来优化渲染
在渲染优化中使用memo、useCallback和React.useMemo进行优化。
在React开发中,可以通过在开发过程中注意重新渲染的问题来提高性能。为了控制重新渲染,可以使用缓存技术,包括React.memo、useCallback和React.useMemo。
备忘录类型
通过对React进行记忆化,可以控制和优化重新渲染。
记忆化是通过保留上次的处理结果来加快处理速度。
種類対象React.memoコンポーネントuseCallbackコールバック関数React.useMemo変数
再渲染发生的条件。
-
- 被 State 更新的组件
-
- 被 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>
);
};
在上述代码执行之后,当你按下计数按钮时,你可以确认所有组件都被重新渲染了,效果如下。
使用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>
);
});
通过记忆化,我们可以确认只有App组件重新渲染了。
尝试通过函数进行再渲染。
我写了一个函数来重置计数按钮,并创建了将函数传递给Child1的代码。当执行计数增加时,会导致Child1重新渲染,这就是之前记忆化的问题。
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 不再重新渲染。
在React中可以使用React.useMemo来进行变量的记忆化。
要实现变量和值的记忆化,我们可以使用React的useMemo函数。第一个参数传入计算式,第二个参数传入依赖数组的元素。只有依赖数组的元素发生变化时,才会重新计算记忆化的值。在下面的代码中,如果a和b的值不变,那么将重复使用首次渲染时的值。
const memoizedValue = useMemo(() => {
return a + b;
}, [a, b]);