当多次重复点击按钮时,以下三个 Heading 是如何渲染的
更多描述
import React, { memo, useMemo, useState } from "react";
const Heading = memo(({ style, title }) => {
console.log("Rendered:", title);
return <h1 style={style}>{title}</h1>;
});
export default function App() {
const [count, setCount] = useState(0);
const normalStyle = {
backgroundColor: "teal",
color: "white",
};
const memoizedStyle = useMemo(() => {
return {
backgroundColor: "red",
color: "white",
};
}, []);
return (
<>
<button
onClick={() => {
setCount(count + 1);
}}
>
Increment {count}
</button>
<Heading style={memoizedStyle} title="Memoized" />
<Heading style={normalStyle} title="Normal" />
<Heading title="React.memo Normal" />
</>
);
}
Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 512
Author 回答者: buzuosheng
“Memoized”只在第一次渲染时打印一次,后续点击不刷新。 “Normal”会在每次渲染时打印。 “React.memo Normal”只会在第一次渲染时打印一次。
使用useMemo
时,依赖数组为null,这意味着只会在首次渲染时,对memoizedStyle进行一次计算,后续不再计算。
在渲染`
memoizedStyle === memoizedStyle; //true
由于状态始终是一个对象,自身始终是与自身相等的,所以不会导致重新渲染。
没有使用useMemo
时,每次点击,对<Heading />
组件传入属性,React.memo判断
{
backgroundColor: "teal",
color: "white",
} === {
backgroundColor: "teal",
color: "white",
} // false
每次都会传入一个新的对象,由于React.memo对prop进行浅比较,两个对象总是不相等的。 如果需要进行深比较,可以对React.memo传入一个深比较函数作为第二个参数。
“React.memo Normal”的参数是字符串,相比对象的比较简单了很多,所以不会导致重新渲染。