簡體   English   中英

為什么我的卡片列表組件在每次更改時都會重新渲染

[英]Why does my Card List Component Re-renders on every change

我確實了解 useEffect,也許並不完全了解,但由於一些警告,我使用 useCallBack 重新構建了一些函數,這似乎解決了警告問題。 問題是我不完全理解 useCallBack,而且由於時間緊迫,我無法閱讀文檔並正確理解它。 因此,每次更改時,我都會再次重新渲染相同的列表

這是我的代碼:

    const getTeamById = useCallback(async (teamId) => {
    await ligaApi.get(`/teams/${teamId}/players`).then((res) => {
        const response = res.data;
        const getPlayerDataRequests = response?.map((x) => x.playerId);

        Promise.all(getPlayerDataRequests).then((res) => {
            for (let i = 0; i < res.length; i++) {
                const playerData = res[i];
                getPlayerData(playerData);
            }
        });
    });
}, []);

const getPlayersTeams = useCallback(
    async (playerId) => {
        await ligaApi.get(`/players/${playerId}/teams`).then((res) => {
    

            setTeamID(res.data[0].teamId);
            getTeamById(teamID);
        });
    },
    [getTeamById, teamID]
);
useEffect(() => {
    getPlayersTeams(playerId);
}, [getPlayersTeams, playerId]);

const getPlayerData = async (playerId) => {
    await ligaApi.get(`/players/${playerId}`).then((res) => {
        const response = res.data;
        setIsLoading(true);
        setPlayers((prevState) => [...prevState, response]);
    });
};

我注意到您的 getPlayersTeams function 中有一個錯誤,我在下面的代碼中修復了它:

  const getPlayersTeams = useCallback(
    async (playerId) => {
        await ligaApi.get(`/players/${playerId}/teams`).then((res) => {

    const dataTeamId = res.data[0].teamId

            setTeamID(dataTeamId);
            getTeamById(dataTeamId);
        });
    },
    [getTeamById, teamID]
);

您無法在設置后訪問 state teamId,因為它是異步的,在您的情況下,您將 teamId 的先前值傳遞給您的 dataTeamId function

主要問題在於您的getPlayersTeamsuseEffect掛鈎。

const getPlayersTeams = useCallback(
  async (playerId) => {
    await ligaApi.get(`/players/${playerId}/teams`).then((res) => {
      setTeamID(res.data[0].teamId); 
      getTeamById(teamID); // here, teamID is not yet set.
    });
  },
  [getTeamById, teamID] // here, you have teamId locally, dont take it from state
);
useEffect(() => {
  getPlayersTeams(playerId);
}, [getPlayersTeams, playerId]); // here, function updates state variable and also depends on this state variable, circular.

useEffect將在其任何依賴項發生更改時觸發。 因此它會在getPlayersTeams更新時觸發。 並且由於它的 deps 數組中有teamID並且它本身使用setTeamID設置團隊 id 而被更新。

關於getPlayersTeams的問題在此處的另一個答案中進行了描述,但它不能解決問題。 僅僅因為您必須從其[depsArray]中刪除teamID 因為它不再在里面使用了。 循環更新將消失。

const getPlayersTeams = useCallback(
  async (playerId) => {
    const res = await ligaApi.get(`/players/${playerId}/teams`);
    const teamId = res.data[0].teamId;
    setTeamID(teamId);
    await getTeamById(teamId); // also await
  },
  [getTeamById]
);

此外,建議將 API 調用與 UI 更新分開,不要執行 API 調用並在 1 方法中設置 state。 並且要密切注意承諾的處理,在你的代碼中有幾個地方沒有等待它們。 即使它現在不會導致錯誤和錯誤 - 有一天它們會。

好的,經過評論討論 - 找到下一個問題 - players數組沒有重新設置,並且一遍又一遍地積累。

useEffect(() => {
  setPlayers([]); // reset to empty array when playerId changed
  getPlayersTeams(playerId);
}, [getPlayersTeams, playerId]);

下一個建議 - 不要將async.then()混合使用。

暫無
暫無

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

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