簡體   English   中英

React useState 導致“無法在未安裝的組件上執行 React 狀態更新..”錯誤

[英]React useState causing “Can't perform a React state update on an unmounted component..” error

我是 React/Node 的新手,正在從事一個學習項目。 這是一個將用戶(自由職業者)與非營利公司聯系起來的平台。 當用戶登錄時,他們可以轉到 UserConnections 頁面以查看他們連接的所有公司。

這工作正常,但我也收到警告Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. 此外,當我訪問此組件時,命令行開始以極快的速度無休止地吐出連接消息。

我認為問題來自 UserConnections 組件中使用的這個useEffect 這段代碼寫起來很痛苦,需要這里多人的幫助才能寫出來。 我很猶豫要不要碰它。

useEffect(() => {        
      const comps = connections.map((c) => VolunteerApi.getCurrentCompany(c));
      Promise.all(comps).then((comps => setCompanies(comps)));
    }    
  }, [connections]);  

我試着像這樣重寫它:

useEffect(() => {
    let isMounted = true;
    const comps = connections.map((c) => VolunteerApi.getCurrentCompany(c));
    if (isMounted) {
      Promise.all(comps).then((comps => setCompanies(comps)));
    }
    return () => { isMounted = false };        
  }, [connections]);

但這根本沒有改變任何事情。

如何更改此代碼以避免內存泄漏而不影響此功能的預期用途? 下面是這個組件的代碼。 感謝您的任何幫助。

用戶連接

function UserConnections() {
  const { currentUser, connectionHandles } = useContext(UserContext);
  const connections = currentUser.connections.concat(connectionHandles);
  const [companies, setCompanies] = useState([]);

  useEffect(() => {
    const comps = connections.map((c) => VolunteerApi.getCurrentCompany(c));
    Promise.all(comps).then((comps => setCompanies(comps)));
  }, [connections]);

  if (!companies || companies.length == 0) {
    return (
      <div>
        <p>You have no connections</p>
      </div>
    )
  } else {
    return (
      <div>
        {companies && companies.map(c => (
          <CompanyCard
            key={c.companyHandle}
            companyHandle={c.companyHandle}
            companyName={c.companyName}
            country={c.country}
            numEmployees={c.numEmployees}
            shortDescription={c.shortDescription}
          />
        ))}
      </div>
    );
  }
};

您在重寫時幾乎正確( isMounted !) - isMounted檢查需要進入then

代替:

    if (isMounted) {
      Promise.all(comps).then((comps => setCompanies(comps)));
    }

你這樣寫:

      Promise.all(comps).then(comps => isMounted && setCompanies(comps));

這也只是一個警告。 你應該修復它,是的,但這不是瘋狂的關鍵。

編輯:

無限循環問題:

const connections = currentUser.connections.concat(connectionHandles);

每次重新渲染組件(調用setCompanies )時,連接useEffect發生變化,因此useEffect引用會發生變化。 修復它的方法是使用connectionHandlescurrentUser作為效果的依賴項,並在效果內部移動connections ,例如:

function UserConnections() {
  const { currentUser, connectionHandles } = useContext(UserContext);
  const [companies, setCompanies] = useState([]);

  useEffect(() => {
    let isMounted = true;
    // move connections inside the effect
    const connections = currentUser.connections.concat(connectionHandles);
    const comps = connections.map((c) => VolunteerApi.getCurrentCompany(c));
    Promise.all(comps).then((comps => isMounted && setCompanies(comps)));
    return () => { isMounted = false };
  }, [currentUser,connectionHandlers]);


...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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