Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

104
Visualizações
setState loop seems to only run on the last iteration

So I have an app with friends and events, where each friends has specific events.
I just want to retrieve every single event from every single friend.
I have an 'event' state const [events, setEvents] = useState([]);
Then here is the problematic useEffect snippet:

useEffect(() => {
  getFriendsIds()
    .then(idsArray => {
      Promise.all(idsArray.map(id => {
        getUserEvents(id)
          .then(evs => {
            if (evs.length > 0) {
              for (let i=0; i<evs.length; i++) {
                setEvents([...events, evs[i]]);
              }
            }
          })
      }))
    })
}, [])

This should store the aforementioned events in the 'events' state variable.
However, when I try to render them with {events.map(ev => renderItem(ev))}, I only get the very last event of the last friend in the loop (It is guaranteed that renderItem works fine).
I would love an explanation of how this works, and if possible an alternative algorithm that actually achieves what I aim to do.
Thanks

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

Actually, this happens because your useEffect() doesn't have the events state in its dependency array.

useEffect(() => {
   ...
}, [events])

However event this solution will not work properly because the setState() function works asynchronously.

You have to use state updater function in this case:

useEffect(() => {
  ...
  setEvents((prevEvents) => [...prevEvents, evs[i]]);
  ...
}, []);

Read more about dependency array and state updater in the official documentation

about 4 years ago · Juan Pablo Isaza Relatório

0

Try passing a function to setEvents and remove the for loop.

if (evs.length > 0) {
    setEvents((prev) => ([...prev, ...evs]));
}
about 4 years ago · Juan Pablo Isaza Relatório

0

Move the setState out of the loop -

useEffect(async () => {
  const ids = await getFriendsIds()
  const events = await Promise.all(ids.map(getUserEvents)))
  setEvents(events.flat())      // replace
}, [])

If you want to append events to the existing events state, you can use a functional update -

useEffect(async () => {
  const ids = await getFriendsIds()
  const events = await Promise.all(ids.map(getUserEvents)))
  setEvents(r => [...r, ...events.flat()])    // append
}, [])

You can use .flat instead of checking for .length as it will remove empty arrays for you automatically -

const a = [["event1", "event2"], [], ["event3"], ["event4"], []]

console.log(a.flat())
// ["event1", "event2", "event3", "event4" ]

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda