You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next+Express+Socket.io聊天应用接收消息时状态重置问题

问题解决:聊天应用消息数组状态重置

问题根源

你的问题出在前端状态更新的方式上。addMessage函数里使用了闭包捕获的messages旧值来构建新数组,当组件多次渲染后,闭包保留的始终是初始或更早的messages状态,导致每次更新都会覆盖之前的消息,而非追加新消息。

修复方案

将状态更新改为函数式更新,直接利用React提供的前一次状态值构建新数组,彻底避免闭包陷阱;同时完善useEffect的依赖管理,防止旧回调导致的异常。

修改后的前端代码

import io from 'socket.io-client'
import { useEffect, useState } from 'react'

const socket = io.connect("http://localhost:3001")

export default function Home() {
  const [chat, setChat] = useState("")
  const [message, setMessage] = useState("")
  const [messages, setMessages] = useState([])

  const joinChat = () => {
    if(chat)
      socket.emit("join_chat", chat)
  }

  // 改用函数式更新,基于前一次状态构建新数组
  const addMessage = (newMessage) => {
    setMessages(prevMessages => [...prevMessages, newMessage])
  }

  const sendMessage = () => {
    socket.emit("send_message", {
      message,
      chat,
    })
    addMessage(message)
    // 可选优化:发送后清空输入框
    setMessage("")
  }
  
  useEffect(() => {
    const handleReceiveMessage = (data) => {
      addMessage(data.message)
    }
    socket.on("receive_message", handleReceiveMessage)
    
    // 清理函数:组件卸载时移除监听,避免内存泄漏
    return () => {
      socket.off("receive_message", handleReceiveMessage)
    }
  }, [addMessage]) // 加入依赖,确保回调使用最新的addMessage

  return (
    <div>
      <input type="text"
        value={chat}
        placeholder="Chat room number"
        onChange={(e) => setChat(e.target.value)}
      />
      <button onClick={joinChat}>Join Chat</button>

      <input type="text"
        value={message}
        placeholder="Message"
        onChange={(e) => setMessage(e.target.value)}
      />
      <button onClick={sendMessage}>Send Message</button>

      <h1>Messages</h1>
      <ul>
        {messages.map((msg, index) => 
          <li key={index}>{msg}</li>
        )}
      </ul>
    </div>
  )
}

优化说明

  • 函数式更新:setMessages(prev => [...prev, newMessage])确保每次更新都基于最新的状态,彻底解决闭包导致的状态重置问题。
  • Socket监听清理:在useEffect返回函数中移除监听,避免组件卸载后仍接收消息引发内存泄漏。
  • 依赖数组完善:将addMessage加入依赖,React会在函数更新时重新绑定监听,保证回调逻辑始终有效。

内容的提问来源于stack exchange,提问作者TcsssT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:48:17