grayson
grayson

Reputation: 1037

React useState, setState in useEffect not updating array

I've seen this problem on SO, but I cannot seem to work out why it exists.

I am following the tutorial from here

I am using useState but when I try to update the state, the array is empty. I am using state to create initially an empty array. on message received, I am trying to add the message to the array, using the spread operator, which I have used countless times to add an object to an array (but never inside useEffect).

If I uncomment the commented lines, "chat" gets updated as it should do, but I cannot understand why the spread operator is not working and I need to use a useRef to make this work. I don't want to have loads of useRef for every corresponding useState (at least not knowing why it is necessary)

Can anyone see what I am doing wrong, or explain why I need the useRef?

const [chat, setChat ] = useState([]);

//const latestChat = useRef(null);
//latestChat.current = chat;

// ...

useEffect(() => {
    if (connection) {
        connection.start()
            .then(result => {
                console.log('Connected!');

                connection.on('ReceiveMessage', message => {
                    const newMsg = {
                        user: message.user,
                        message:message.message
                    }
                    setChat([...chat, newMsg]); // issue with this line. chat is always empty

                    //const updatedChat = [...latestChat.current];
                    //updatedChat.push(message);
                    //setChat(updatedChat);
                    
                    
                });
            })
            .catch(e => console.log('Connection failed: ', e));
    }
}, [connection]);

Upvotes: 3

Views: 4400

Answers (1)

Taghi Khavari
Taghi Khavari

Reputation: 6582

you have two option here

  1. add chat state to useEffect dependency array so it knows it depends on chat.
useEffect(() => {
  if (connection) {
    //...
    setChat([...chat, newMsg]); // issue with this line. chat is always empty
    //...
  }
}, [connection, chat]);
  1. use setState callback to update chat so you won't get stale data
useEffect(() => {
  if (connection) {
    //...
    setChat((ch) => [...ch, newMsg]); // issue with this line. chat is always empty
    //...
  }
}, [connection]);

which the second way is more appropriate.

Upvotes: 8

Related Questions