实现的需求:在列表中如何缓存每个子组件,父组件重新渲染,子组件不更新,下面的列子假设 Chart
组件被包裹在memo
中。你希望在 ReportList
组件重新渲染时跳过重新渲染列表中的每个 Chart
。但是,你不能在循环中调用 useCallback
。
实现效果
- 代码逻辑
ReportList.js
import { useCallback, useState } from "react";
import Chart from "./Chart";
function sendReport(item) {
console.log("Sending report for", item);
}
function ReportList({ items }) {
const [msg, setMsg] = useState("hello");
function handleChange(e) {
setMsg(e.target.value);
console.log(msg);
}
return (
<article>
{items.map((item) => {
// 🔴 你不能在循环中调用 useCallback:
// const handleClick = useCallback(() => {
// sendReport(item)
//}, [item]);
//return (
// <figure key={item.id}>
// <Chart onClick={handleClick} />
// </figure>
//);
return <Report key={item.id} item={item} />;
})}
<input type="text" value={msg} onChange={handleChange} />
</article>
);
}
function Report({ item, onClick }) {
const handleClick = useCallback(() => {
sendReport(item);
}, [item]);
return (
<figure key={item.id}>
<Chart onClick={handleClick} />
</figure>
);
}
export default ReportList;
注意:我们不能在迭代中使用useCallback
Chart.js
function Chart({ onClick }) {
console.log("chart");
return <button onClick={onClick}>Send Report</button>;
}
export default Chart;
发现chart组件还是会重新渲染,这个不是我们想要的效果。对代码进行改写
import { memo } from "react";
const Chart = memo(function ({ onClick }) {
console.log("chart");
return <button onClick={onClick}>Send Report</button>;
});
export default Chart;
这样,我们就实现了效果。