Home > OS >  Avoid infinite loop when updating
Avoid infinite loop when updating

Time:11-27

I have to update a state of items and see the changes right away. When I'm doing this below, I get an infinite loop.

 useEffect(() => {
    const playersInFight = gameData.characters.filter((x) =>
      fightData.currentPositionInfoDTOS.some((y) => y.entityId == x.id)
    );

    let orderedCharacters = addPlayers(
      playersInFight,
      fightData.currentPositionInfoDTOS,
      fightData.turnOrder
    );
    setAllCharacterCards(orderedCharacters);

  }, [fightData, gameData, fightInfo, allCharacterCards, allCharacters]);

I have tried also like this:

  useEffect(() => {
    const playersInFight = gameData.characters.filter((x) =>
      fightData.currentPositionInfoDTOS.some((y) => y.entityId == x.id)
    );

    let orderedCharacters = addPlayers(
      playersInFight,
      fightData.currentPositionInfoDTOS,
      fightData.turnOrder
    );
    setAllCharacterCards(orderedCharacters);

  }, [fightData, gameData, fightInfo, allCharacterCards, allCharacters]);

  useEffect(() => {
    setAllCharacterCards(allCharacterCards);
  }, [allCharacterCards]);

And thanks to that I don't have an infinite loop, but to see the changes I have to refresh the page... How can I solve this?

Update: Here is my return:

return (
    <section>
        <div className="player-fight">
          {allCharacterCards ? (
            <div>
              {allCharacterCards.map((c, idx) => {
                return (
                  <li key={idx} className="player-fight-bottom__player-card">
                    <CardComponentPlayerCard
                      id={c.id}
                      name={c.name}
                      money={c.money}
                      health={c.health}
                      maxHealth={c.maxHealth}
                      mine={false}
                      description={c.description}
                      statuses={c.statuses}
                      image={c.photoPath}
                    />
                  </li>
                );
              })}
            </div>
          ) : (
            <LoadingSpinner />
          )}
        </div>
    </section>
  );

CodePudding user response:

To avoid infinite looping you need to remove allCharacterCards from useEffect dependency array.

 useEffect(() => {
    const playersInFight = gameData.characters.filter((x) =>
      fightData.currentPositionInfoDTOS.some((y) => y.entityId == x.id)
    );

    let orderedCharacters = addPlayers(
      playersInFight,
      fightData.currentPositionInfoDTOS,
      fightData.turnOrder
    );

    setAllCharacterCards([...orderedCharacters]);

  }, [fightData, gameData, fightInfo, allCharacters]);

Explanation (after question edited)

    setAllCharacterCards([...orderedCharacters]);

This should fix your problem.

Since allCharacterCards is an array of objects you need to use spread operator ... to let react know that you are updating state everytime with new values. Read more about - Deep copy vs shallow copy.

  • Related