Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

175
Views
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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!