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

ReactJS中数组无法保存消息数据的技术求助

问题分析与解决方案

问题根源

  1. 第一种写法将chat作为useEffect的依赖项,每次chat更新都会重新创建socket连接并订阅事件,导致重复监听,进而引发状态更新异常。
  2. 第二种写法仅初始化一次监听,但setChat使用的是组件挂载时的chat闭包值(初始空数组),所以每次更新都是[...[], {message}],最终数组永远只保留最新一条消息。

修复后的完整代码

import './App.css';
import io from 'socket.io-client'
import { useEffect, useRef, useState } from 'react'

// 全局初始化一次socket连接,避免重复创建实例
const socket = io.connect("http://localhost:3001");

function App() {
  const [message, setMessage] = useState("");
  const [chat, setChat] = useState([]);
  // 保存监听回调引用,用于卸载时移除监听
  const messageListenerRef = useRef();

  const sendMessage = () => {
    socket.emit("send_message", { message });
    // 发送后清空输入框,优化体验
    setMessage("");
  };

  const renderChat = () => {
    return chat.map((msg, index) => (
      // 给列表元素加唯一key,符合React渲染规范
      <h3 key={index}>{msg.message}</h3>
    ));
  };

  useEffect(() => {
    // 定义消息接收回调
    const handleReceiveMessage = ({ message }) => {
      // 使用函数式更新state,确保拿到最新的chat状态
      setChat(prevChat => [...prevChat, { message }]);
    };

    socket.on("receive_message", handleReceiveMessage);
    messageListenerRef.current = handleReceiveMessage;

    // 组件卸载时移除监听,避免内存泄漏
    return () => {
      socket.off("receive_message", messageListenerRef.current);
    };
  }, []); // 空依赖数组,仅在组件挂载时执行一次

  return (
    <div className="App">
      <input
        placeholder="Message..."
        value={message}
        onChange={(event) => setMessage(event.target.value)}
      />
      <button onClick={sendMessage}>Send Message</button>
      <h1>Messages:</h1>
      {renderChat()}
    </div>
  );
}

export default App;

关键修复点

  • 函数式更新state:通过setChat(prevChat => [...prevChat, { message }])获取最新状态值,彻底规避闭包导致的旧值问题。
  • 单一socket实例:全局初始化socket连接,避免重复创建连接造成资源浪费。
  • 监听生命周期管理:仅在组件挂载时订阅一次事件,卸载时移除监听,防止内存泄漏和重复触发。
  • 列表渲染规范:给渲染的消息元素添加唯一key,消除React控制台警告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 05:35:21