I do understand useEffect, perhaps not entirely , but due to some warnings, I re-structured some of my functions with useCallBack and that seemed to resolve the warning issue. The thing is I don't understand useCallBack fully, and due to tight schedule I'm unable to read the documentation and understand it properly. So I'm stuck re-rendering the same list again with every change
Here is my code:
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]);
});
};
CodePudding user response:
I noticed an error in your getPlayersTeams function, I fixed that in the code below:
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]
);
You can't access the state teamId just after setting it because it is asyncronous, in your case you were passing the previous value of teamId to your dataTeamId function
CodePudding user response:
The main issues are in your getPlayersTeams
and useEffect
hook.
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
will be triggered when any of its dependencies changes. So it triggers when getPlayersTeams
is updated. And it is updated due to it has teamID
in its deps array and itself it sets team id with setTeamID
.
Issue about getPlayersTeams
is described in another answer here but it does not fix the issue. Just because you had to remove teamID
from its [depsArray]
. Because it is not used inside of it anymore. Circular updates will be gone.
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]
);
Also, recommendation, separate API calls from UI updates, do not execute API calls and setting state in 1 method. And do keep an eye on promises handling, there is a few places in your code where they are not awaited. Even if it is not causing errors and bugs now - one day they will.
Ok, after discussions in comments - next issue was found - players
array was not re-seted and was accumulated over and over.
useEffect(() => {
setPlayers([]); // reset to empty array when playerId changed
getPlayersTeams(playerId);
}, [getPlayersTeams, playerId]);
Next recommendation - dont mix async
with .then()
.