記憶回呼函式是如何作業的?在一些文章中,我讀到如果我們不使用 useCallback,就會重新創建該函式。但是如果重新創建,它應該與之前的版本不同嗎?在我的代碼中,我沒有注意到回呼函式存在差異。 我的問題是:為什么在這兩種情況下,我的設定大小都是 1?
來自關閉檔案 useCallback
回傳一個記憶化的回呼。
傳遞一個行內回呼和一組依賴項。useCallback 將回傳回呼的記憶版本,僅當其中一個依賴項發生更改時才會更改。這在將回呼傳遞給優化的子組件時很有用,這些子組件依賴于參考相等來防止不必要的渲染(例如 shouldComponentUpdate)。
import { useCallback } from "react";
const dataSource = [
{
id: 1,
model: "Honda",
color: "red",
},
{
id: 2,
model: "Mazda",
color: "yellow",
},
{
id: 3,
model: "Toyota",
color: "green",
},
];
const Car = ({ model, color, set, onCarClick }) => {
const onClick = () => onCarClick(model, color);
set.add(onCarClick);
console.log(set.size);
return (
<div onClick={onClick}>
Model: {model} Color: {color}
</div>
);
};
const CarsCallback = ({ cars, set }) => {
const onCarClick = (model, color) => {
console.log(model, color);
};
console.log("CarsCallback");
return (
<>
{cars.map((car) => {
return (
<Car
key={car.id}
set={set}
{...car}
onCarClick={onCarClick}
/>
);
})}
</>
);
};
const CarsUseCallback = ({ cars, set }) => {
const onCarClick = useCallback((model, color) => {
console.log(model, color);
}, []);
console.log("CarsUseCallback");
return (
<>
{cars.map((car) => {
return (
<Car
key={car.id}
{...car}
set={set}
onCarClick={onCarClick}
/>
);
})}
</>
);
};
export default function App() {
return (
<div className="App">
<CarsCallback cars={dataSource} set={new Set()} />
<CarsUseCallback cars={dataSource} set={new Set()} />
</div>
);
}
uj5u.com熱心網友回復:
因為CarsUseCallbackandCarsCallback被觸發過一次。
CarsUseCallback我們可以看到和的唯一一個對數CarsCallback。
如果我們重新渲染CarsUseCallbackand CarsCallback,我們可以看到大小是1and 2。
const CarsCallback = ({ cars, set }) => {
const [count, setCount] = useState(1);
console.log('CarsCallback');
useEffect(() => {
setCount(2);
}, []);
// ...
};
const CarsUseCallback = ({ cars, set }) => {
const [count, setCount] = useState(1);
console.log('CarsUseCallback');
useEffect(() => {
setCount(2);
}, []);
// ...
}
uj5u.com熱心網友回復:
在一些文章中,我讀到如果我們不使用 useCallback 會重新創建該函式
無論您是否使用useCallback鉤子,都會重新創建函式。不同之處在于,如果鉤子的依賴關系沒有改變useCallback,則丟棄重新創建的函式并回傳記憶化的函式。useCallback
但是如果重新創建,它應該與之前的版本不同嗎?
是的,每個新函式參考都是不同的函式,即不同的物件。
在我的代碼中,我沒有注意到回呼函式存在差異。我的問題是:為什么在這兩種情況下,我的設定大小都是 1?
因為您需要重新渲染組件才能重新創建功能。在您的代碼中,回呼函式僅在兩個組件中創建一次,因此 的大小Set始終為 1。
此外,您需要擺脫Car組件內的以下代碼行:
const onClick = () => onCarClick(model, color);
您要添加的Set是onCarClick作為道具從父組件傳遞的函式。使用onClick,無論您是否使用useCallback鉤子,您總是在創建一個新函式。
下面demo展示了useCallbackhook的效果。單擊重新渲染按鈕以渲染組件,導致重新創建回呼函式。
const dataSource = [
{ id: 1, model: "Honda", color: "red" }
];
const Car = ({ model, color, set, onCarClick }) => {
//const onClick = () => onCarClick(model, color); // remove this
set.add(onCarClick);
console.log(set.size);
return (
<div onClick={onCarClick}>
Model: {model} Color: {color}
</div>
);
};
const CarsCallback = ({ cars, set }) => {
const onCarClick = (model, color) => {
console.log(model, color);
};
console.log("CarsCallback");
return (
<div>
{cars.map((car) => {
return <Car key={car.id} set={set} {...car} onCarClick={onCarClick} />;
})}
</div>
);
};
const CarsUseCallback = ({ cars, set }) => {
const onCarClick = React.useCallback((model, color) => {
console.log(model, color);
}, []);
console.log("CarsUseCallback");
return (
<div>
{cars.map((car) => {
return <Car key={car.id} {...car} set={set} onCarClick={onCarClick} />;
})}
</div>
);
};
const set1 = new Set();
const set2 = new Set();
function App() {
const [state, setState] = React.useState();
return (
<div className="App">
<CarsCallback cars={dataSource} set={set1} />
<CarsUseCallback cars={dataSource} set={set2} />
<button onClick={() => setState({})}>Re-render</button>
</div>
);
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/417649.html
標籤:
