[英]Infinite Loop with useEffect - ReactJS
我在使用 useEffect 鈎子時遇到問題,它生成了一個無限循環。
我有一個在頁面組裝后立即加載的列表,並且在“開發人員”狀態下發現新記錄時也應該更新。
看代碼:
const [developers, setDevelopers] = useState<DevelopersData[]>([]);
const getDevelopers = async () => {
await api.get('/developers').then(response => {
setDevelopers(response.data);
});
};
// This way, the loop does not happen
useEffect(() => {
getDevelopers();
}, []);
// This way, infinte loop
useEffect(() => {
getDevelopers();
}, [developers]);
console.log(developers)
如果我刪除開發人員對 useEffect 的第二個參數的依賴,則不會發生循環,但是,在找到新記錄時不會更新列表。 如果我在 useEffect 的第二個參數中插入“developers”,列表會自動更新,但是,它會進入無限循環。
我究竟做錯了什么?
完整代碼(帶組件): https : //gist.github.com/fredarend/c571d2b2fd88c734997a757bac6ab766
useEffect
的依賴使用引用相等,而不是深度相等。 (如果出於某種原因需要進行深度相等比較,請查看use-deep-compare-effect
。)
API 調用總是返回一個新的數組對象,因此它的引用/標識與之前的不一樣,觸發useEffect
再次觸發效果等。
鑒於沒有其他任何東西調用setDevelopers
,即developers
無法更改,除非它來自效果觸發的 API 調用,因此實際上沒有實際需要讓developers
作為useEffect
的依賴useEffect
; 你可以有一個空數組作為 deps: useEffect(() => ..., [])
。 該效果只會被調用一次。
編輯:在評論澄清之后,
我在左側的表格中注冊了一名開發人員 [...] 我希望在注冊新開發人員后立即更新列表。
這是做事的一種方式:
這里的想法是developers
只會在組件安裝時自動加載。 當用戶通過AddDeveloperForm
添加新開發developers
時,我們會在將新開發人員發布到后端的同時機會性地更新本地developers
狀態。 無論發布是否失敗,我們都會從后端重新加載列表以確保我們擁有最新的真實狀態。
const DevList: React.FC = () => {
const [developers, setDevelopers] = useState<DevelopersData[]>([]);
const getDevelopers = useCallback(async () => {
await api.get("/developers").then((response) => {
setDevelopers(response.data);
});
}, [setDevelopers]);
useEffect(() => {
getDevelopers();
}, [getDevelopers]);
const onAddDeveloper = useCallback(
async (newDeveloper) => {
const newDevelopers = developers.concat([newDeveloper]);
setDevelopers(newDevelopers);
try {
await postNewDeveloperToAPI(newDeveloper); // TODO: Implement me
} catch (e) {
alert("Oops, failed posting developer information...");
}
getDevelopers();
},
[developers],
);
return (
<>
<AddDeveloperForm onAddDeveloper={onAddDeveloper} />
<DeveloperList developers={developers} />
</>
);
};
問題是您的getDevelopers
函數調用了setDevelopers
函數,該函數更新了您的developers
變量。 當您的developers
變量更新時,它會觸發useEffect
函數
useEffect(() => {
getDevelopers();
}, [developers]);
因為developers
是傳遞給它的依賴項之一,並且該過程重新開始。
每次更新數組中作為 useEffect 的第二個參數的變量時,都會觸發useEffect
函數
在 useEffect 的第二個參數中使用空數組[]
。 這會導致內部代碼僅在父組件的安裝上運行。
useEffect(() => {
getDevelopers();
}, []);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.