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

176
Visualizações
React js pushing new object to array always replace last object instead of insert

I am having message listing, and appending live message received from socket, one object inserted from socket, but after that it always replace the last one instead of insert new.

const [chatList, setChatList] = useState(props.chatList ? props.chatList : []);

useEffect(() => {

    const messageListener = (message) => {
        console.log('message',message);
        console.log('chatList',chatList);

        if(message.conversation_id == props.conversation_id){

                const updatedMsgs = [...chatList,message];
                setChatList(updatedMsgs);
        }
        
    };
  
    socket.on('myEventName', messageListener);

    return () => {
      socket.off('myEventName', messageListener);
    };
  }, [props.conversation_id]);

New message and Messagelist log look like enter image description here

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

0

Looks like a stale enclosure of the chatList state. Use a functional state update to update from the previous state and not the state value closed over in callback scope, setChatList(list => [...list, message]);.

useEffect(() => {
  const messageListener = (message) => {
    console.log('message',message);
    console.log('chatList',chatList);

    if (message.conversation_id == props.conversation_id) {
      setChatList(list => [...list, message]);
    } 
  };

  socket.on('myEventName', messageListener);

  return () => {
    socket.off('myEventName', messageListener);
  };
}, [props.conversation_id]);
about 4 years ago · Juan Pablo Isaza Relatório

0

This issue does occurs due to the Stale Closures in Javascript.

Hooks heavily rely on JavaScript closures. That's why hooks are so expressive and simple. But closures are sometimes tricky.

Here is the example:

function DelayedCount() {
  const [count, setCount] = useState(0);
  function handleClickAsync() {
    setTimeout(function delay() {
      setCount(count + 1);
    }, 1000);
  }
  return (
    <div>
      {count}
      <button onClick={handleClickAsync}>Increase async</button>
    </div>
  );
}

If you quickly click the button 2 times, then it increase the count by 1 only, instead of 2.

On each click setTimeout(delay, 1000) schedules the execution of delay() after 1 second. delay() captures the variable count as being 0.

Both delay() closures (because 2 clicks have been made) update the state to the same value: setCount(count + 1) = setCount(0 + 1) = setCount(1).

All because the delay() closure of the second click has captured the outdated count variable as being 0.

To fix the problem, We need to use a functional way setCount(count => count + 1) to update count state:

...
function handleClickAsync() {
  setTimeout(function delay() {
    setCount(count => count + 1);
  }, 1000);
}
...

Now the button does work as expected.

Here is the complete article which may help you to understand about Stale Closures. Article Link

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