Home > Software design >  React Typescipt : UseState of Object Array only updates once in for loop
React Typescipt : UseState of Object Array only updates once in for loop

Time:12-11

So I'm kind of new in typescript and trying something out. I want to randomize X quantity of players betweent X quantity of teams/groups to play a game with.( react native ts mobile app)

Weird behavior (atleast for me) the for loop that I'm using to update the teams in a state array does runs twice because I can see it in the logs and if I save my VS code document the second update in the state array does occus, but ofcourse I want it right the first time.

const [groupsWPlayer, setGroupsWPlayers] = useState<{title: string; players:string[]}[]>([]);
  const [groups, setGroups] = useState<string[]>(route.params?.groups);
  const [players, setPlayers] = useState<string[]>(route.params?.players);

  const AsignPlayersToGroupsAtRandom =  () => {
    setPlayers(arrayShuffle(players));
    for(let i =0; i <= groups.length-1; i  ){
      console.log(i   " / "   groups.length);
      console.log("Group  =  "   groups[i]);
      setGroupsWPlayers([...groupsWPlayer, {title:groups[i], players:players}])
      }
  }
 {groupsWPlayer.map((group, index) => (
      <View key={index}>
        <Text> title = {group.title}</Text>
      <Text>{group.players}</Text>
      <Text>{groupsWPlayer.length}</Text>
      </View>

LOGS / 0 / 2 LOG Group = Ok (group name) LOG 1 / 2 LOG Group = Niet oke (group name)

But it only renders the last group, not the first and the last, which i wanted to.

So for some reason the setGroupsWPlayers only runs once, doe somebody know why and cares to explain to me why? Even if it's a rookie mistake, i'm trying to learn. Thanks in advance

CodePudding user response:

The issue is due to setGroupsWPlayers is not updating the actual groupsWPlayer immediately. The update will happen only on next render, so basically only the last call from the loop of setGroupsWPlayers is applied. ...groupsWPlayer will always be the same here, so on first render in the for loop you will always get [] from it.

Add a temporal variable to store everything and call setGroupsWPlayers only once, outside of the loop.

const AsignPlayersToGroupsAtRandom = () => {
  setPlayers(arrayShuffle(players));
  const tmp: { title: string; players: string[] }[] = [];
  // or
  // const tmp: { title: string; players: string[] }[] = [...groupsWPlayer];
  for (let i = 0; i <= groups.length - 1; i  ) {
    console.log(i   " / "   groups.length);
    console.log("Group  =  "   groups[i]);
    tmp.push({ title: groups[i], players: players });
  }
  setGroupsWPlayers(tmp);
};

Note: If you also expect players to be updated immediately after setPlayers(arrayShuffle(players)); - that will not happen, it will be updated on the next render only.

  • Related