我看到一篇帖子是关于“如何防止重新渲染,以及过多添加记忆”。
发帖:https://d2.naver.com/helloworld/9223303 (这是韩文写的,我不确定有英文版)
在这中间,它说
消除不必要的记忆的方法之一是使用包装组件可以避免重新渲染子组件 代码如下:
function ChildMemo () {
const [count, setCount] = React.useState(0);
const doubleCount = count * count;
console.log('doubleCount', count * count);
return (
<>
<h2>count: {count}</h2>
<h2>count * count: {doubleCount}</h2>
<button onClick={() => setCount((prev) => prev + 1)}>Click</button>
</>
)
}
function ParentMemo({ children }) {
const [time, setTime] = React.useState(new Date());
React.useEffect(() => {
const intervalId = setInterval(() => {
setTime(new Date());
}, 1000);
return () => {
clearInterval(intervalId);
};
}, []);
return (
<>
<h1>time: {format(time, 'hh:mm:ss')}</h1>
{children}
</>);
}
export default function Memo() {
return <ParentMemo>
<ChildMemo/>
</ParentMemo>
};
(代码来自此帖子)
确实,当我运行上面的代码时,我可以看到子组件没有重新渲染。
供参考, 下面的代码我稍微修改了一下,发生了子组件重新渲染,导致父组件重新渲染并更新状态导致子组件重新渲染。
// this code doesn't have wrapping component, and there's ChildMemo re-rendering
// ChildMemo re-render at every single seconds(ParentMemo component re-rendering)
import "./styles.css";
import * as React from "react";
export default function App() {
return (
<div className="App">
<ParentMemo />
</div>
);
}
function ChildMemo() {
const [count, setCount] = React.useState(0);
const doubleCount = count * count;
console.log("doubleCount", count * count);
return (
<>
<h2>count: {count}</h2>
<h2>count * count: {doubleCount}</h2>
<button onClick={() => setCount((prev) => prev + 1)}>Click</button>
</>
);
}
function ParentMemo({ children }) {
const [time, setTime] = React.useState(new Date());
React.useEffect(() => {
const intervalId = setInterval(() => {
setTime(new Date());
}, 1000);
return () => {
clearInterval(intervalId);
};
}, []);
return (
<>
<h1>time: {time.getTime().toString()}</h1>
<ChildMemo />
</>
);
}
有人知道为什么像上面这样的包装组件可以防止重新渲染吗?
当然!包装器组件可以防止重新渲染,因为它充当父组件和子组件之间的屏障。当父组件重新渲染时,如果子组件不直接依赖于父组件的 state 或 props,则不一定会导致子组件重新渲染。
在提供的示例中,当 ChildMemo 组件包装在 ParentMemo 组件内时,它将 ChildMemo 与父级状态(时间)的更改隔离。由于 ChildMemo 不直接依赖于时间状态,因此当 ParentMemo 由于时间变化而重新渲染时,它不会不必要地重新渲染。这种隔离可以防止不必要的 ChildMemo 重新渲染。