Search code examples
javascriptreactjsreact-hooksuse-effectuse-state

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


Solution

  • 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]);