Marcos utilizados: Next.js, Socket.io, React
Estoy haciendo una aplicación de mensajería simple. Básicamente, solo estoy emitiendo un mensaje que alguien escribe, enviando ese mensaje al servidor, que luego se "transmite" a través de un evento llamado "receive-chat-message". El problema que tengo es que cuando la respuesta se maneja en el front-end con "receive-chat-message", el estado [mensajes] no agrega un nuevo mensaje para mostrar, simplemente sobrescribe el estado.
Mi objetivo es enviar un mensaje al servidor; el servidor luego envía el mensaje al cliente. Luego agrego el nuevo mensaje en el cliente, enviado desde el servidor, al estado de [mensajes] en el cliente, y luego presento el estado de [mensajes]. El problema es que solo sobrescribe el estado de [mensajes] y no le agrega nuevos mensajes.
Código que envía mensaje al servidor
const [message, setMessage] = useState(""); const handleChange = (e) => { setMessage(e.target.value); }; const submitMessage = async () => { // socket.io const socket = io(); socket.emit("send-chat-message", message, user); setMessage(""); };
Código de front-end
const [messages, setMessages] = useState([]); useEffect(() => { const socket = io(); socket.on("receive-chat-message", handleSetMessage); return () => socket.disconnect(); }, []); const handleSetMessage = (data) => { /* data prop is the new message - it has a {message: "message", user: "name"} sent from server. THIS IS THE PROBLEM IN THE CODE WHERE IT DOESN'T APPEND NEW MESSAGES TO THE [messages] STATE, IT JUST OVERWRITES THE CURRENT STATE WITH THE NEW MESSAGE. */ setMessages([...messages, data]); };
Código de back-end
export default async function handler(req, res) { if (!res.socket.server.io) { const io = new Server(res.socket.server); res.socket.server.io = io; io.on("connection", async (socket) => { socket.on("send-chat-message", async (message, user) => { socket.broadcast.emit("recieve-chat-message", { message, name: user && user.name, }); }); }); } }
Resolví esto configurando mensajes a través del método funcional como:
setMessages((messages) => [...messages, data]);
En vez de:
setMessages([...messages, data])
Creo que necesitamos esto porque estaba actualizando el estado desde una función llamada dentro de un oyente socket.io y en realidad nunca estaba tomando el estado anterior; así que tuve que dirigirlo al estado anterior y luego fusionar los valores.