簡體   English   中英

帶有 useEffect 的無限循環 - ReactJS

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM