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

React项目Socket.io房间聊天双向通信故障排查求助

React+Socket.io双向聊天问题解决方案

问题场景

  • 用户登录后进入个人页面,点击目标用户消息按钮进入聊天界面
  • 仅能发送消息,无法接收对方回复
  • 测试日志显示消息已发送且属于同一房间ID,但双方无法收到消息

核心问题分析

  1. Socket实例不统一:父组件和聊天组件各自创建独立的Socket连接,父组件执行join事件的Socket实例与聊天组件收发消息的Socket实例不是同一个,导致聊天组件的Socket未加入目标房间。
  2. 聊天组件未加入房间:即使房间ID正确,聊天组件的Socket未执行join操作,无法接收房间内的广播消息。
  3. 未清理Socket监听:组件卸载时未移除Socket事件监听,可能引发内存泄漏和重复监听问题。

修正步骤

1. 统一Socket实例

将父组件创建的Socket实例传递给聊天组件,避免重复创建连接。

2. 聊天组件加入房间

在聊天组件的useEffect中执行join操作,确保当前Socket实例加入目标房间。

3. 清理Socket监听

组件卸载时移除receive_message监听,防止内存泄漏。

修正后代码

父组件代码调整

const socket = io('http://localhost:8080');

const roomId = [sender, profileFirstName + " " +  profileLastName].sort().join('_');

const messageHandler = () => {
    setRenderMessage(!renderMessage);
};

// 渲染Message组件时传入socket实例
{renderMessage ? (
    <Message
        sender={sender}
        recipient={profileFirstName + " " +  profileLastName}
        profilePicture={profileProfilePicture}
        roomId={roomId}
        socket={socket} // 传递统一的Socket实例
    />
) : (...)}

聊天组件代码调整

import { useEffect, useState, useRef } from 'react';
import { ArrowLongUpIcon } from '@heroicons/react/24/outline';

// 接收父组件传递的socket参数
export default function Message({sender, recipient, profilePicture, roomId, socket}) {
    const [message, setMessage] = useState('');
    const [messages, setMessages] = useState([]);

    const bottomRef = useRef(null);
    
    const sendMessage = () => {
        if (message !== '') {
            const messageData = {
                sender: sender,
                recipient: recipient,
                message: message,
                time: new Date().getHours() + ':' + new Date().getMinutes(),
                room: roomId
            };

            socket.emit('send_message', messageData);
            setMessages((list) => [...list, messageData]);    
            setMessage('');
        };
    };

    useEffect(() => {           
        // 加入目标房间
        socket.emit('join', roomId);

        // 定义消息接收处理函数
        const handleReceiveMessage = (data) => {
            if (data.room === roomId) {
                setMessages((list) => [...list, data]);
            }
        };
        // 绑定消息监听
        socket.on('receive_message', handleReceiveMessage);

        // 组件卸载时清理监听和房间
        return () => {
            socket.off('receive_message', handleReceiveMessage);
            socket.leave(roomId);
        };
    }, [roomId, socket]);

    useEffect(() => {
        bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
      }, [messages]);

    // 其余JSX结构保持不变...
};

后端代码(无需修改)

后端逻辑本身正确,io.to(data.room).emit可正常广播消息至房间内所有连接:

const { Server } = require("socket.io");

const socket = (server) => {
  const io = new Server(server, {
    cors: {
      origin: "*",
      methods: ["GET", "POST"],
    },
  });

  io.on('connection', socket => {    
    socket.on('join', room => {
       socket.join(room);
       console.log('joined room: ' + room);
    });

    socket.on('send_message', (data) => {
      console.log(data);
      io.to(data.room).emit('receive_message', data);
    });
  });
};

module.exports = socket;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 04:16:09