I have the following code :
import { useContext, useState, useEffect } from 'react';
import React from 'react';
import { RoomContext } from '../context/RoomContext';
let nextMessageID = 0
export default function Chat({roomId}) {
const { socket } = useContext(RoomContext)
const [messagesReceived, setMessagesReceived] = useState([]);
useEffect(() => {
socket.on('receive_message', (data) => {
console.log(data.message);
setMessagesReceived([
...messagesReceived,
{ id: nextMessageID++, content: data.message}
]);
})
}, [socket, messagesReceived])
return (
<div>
<h1>Received messages :</h1>
<ul>
{messagesReceived.map(message => {
<li key={message.id}>{message.content}</li>
})}
</ul>
</div>
)
}
which is heavily inspired from the react documentation here : https://react.dev/learn/updating-arrays-in-state#adding-to-an-array
I can see that this code updates my state array "messagesReceived" correctly by adding a button that logs it to the console
<button onClick={() => {
console.log(messagesReceived);
}}>Log messages</button>
but it does not update my component. How can I fix that ?
Also I’m not sure why I need to also execute my effect hook when "messagesReceived" changes but not doing so makes my array only contain the last message. I’d appreciate any explanation on this.
Thank you very much !
2
Answers
In order to avoid creating a closure over the initial state of the
messagesReceived
array in the listener callback you can pass a callback tosetMessagesReceived
which will be passed the up-to-date state. see: React: Updating state based on the previous state. This will also allow you to removemessagesReceived
from the dependency array.You should also always provide a ‘cleanup’ function in your
useEffect
in order to avoid adding multiple listeners. Here assigning the callback to a variable so that the same reference can be used in setting and removing the listener.Lastly, you need to be sure your
map()
callback is returning a value. see: When should I use a return statement in ES6 arrow functionsAdd return in your map function.