Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

177
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda