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

React应用中函数内socket.emit()无法生效求助

Socket.io 客户端 sendMessageHandler 中 emit 无效问题

Socket后端运行正常,已通过Postman验证。问题在于socket.emit在useEffect中可以正常工作,但在sendMessageHandler函数内无法生效。通过日志排查发现,socket.emit("send-message", message)语句前后的日志均正常输出,但该语句似乎未执行。

服务端代码

import { Server } from "socket.io";
import { server } from "./app";
import dotenv from "dotenv";
import { Message } from "./types/message.types";
import deleteUserFromSocketList from "./utils/lib/deleteUserFromSocketList";

dotenv.config();

const io = new Server(server, {
  cors: {
    origin: process.env.CLIENT_URL,
    methods: ["GET", "POST"],
    credentials: true,
  },
});

interface User {
  name: string;
  email: string;
  uid: string;
  sid: string;
}

var connectedUsers: User[] = [];

io.use((socket, next) => {
  //TODO verify user request
  //TODO save or replace user socket id to database
  next();
});

io.on("connection", (socket) => {
  io.to(socket.id).emit("user-sid", { sid: socket.id })

  socket.on("user-details", (user) => {
    connectedUsers = deleteUserFromSocketList(connectedUsers, user);
    connectedUsers.push(user);
    console.log(`user joined: ${socket.id}`);
    io.emit("user-joined", connectedUsers);
  });

  socket.on("send-message", (msg) => {
    // if (msg.receipient.sid.length === 0) return;
    socket.to(msg.receipient.sid).emit("receive-message", msg);
    console.log(msg);
    console.log("message delivered");
  });

  socket.on("disconnect-user", () => {
    const updatedUserList: User[] = [];
    connectedUsers.forEach((user) => {
      if (user.sid !== socket.id) updatedUserList.push(user);
    });
    connectedUsers = updatedUserList
    // socket.disconnect()
    io.emit("user-left", connectedUsers);
  });
});

export { io };

客户端代码

import { useEffect, useState } from "react";
import { getCookie } from "../../utils";
import UsersList from "./userBar";
import CommunicationPanel from "./chatPanel";
import { Message } from "../../types/Message.types";
import { getAllCookies } from "../../utils/getCookie";
import { User } from "../../types/User.types";
import createMessage from "../../utils/createMessage";
import { io } from "socket.io-client";

const URL = process.env.REACT_APP_API_URL || "";

const socket = io(URL, {
  withCredentials: true,
  retries: 5,
  reconnectionDelay: 5000,
  reconnectionAttempts: 3,
  autoConnect: true
});

export default function Dashboard() {

  const [isInitial, setInitial] = useState<boolean>(true);
  const [currSid, setCurrSid] = useState<string>("");
  const [activeChat, setActiveChat] = useState<User | null>(null);
  const [messageList, setMessageList] = useState<Message[]>([]);
  const [onlineUsers, setOnlineUsers] = useState<User[]>([]);


  if (getCookie("isUserLoggedIn") !== "true") {
    window.location.replace("/");
  }

  useEffect(() => {
    function notifyUserConnected() {
      socket.on("user-sid", (connData) => {
        const sid: string = connData.sid;
        setCurrSid(sid);
        const { name, email, uid } = getAllCookies();
        const user = { name, email, uid, sid };
        socket.emit("user-details", user);
      });
    }

    function updateUserList(userList: User[]) {
      setOnlineUsers(userList);
    }

    function updateMessageList(msg: Message) {
      setMessageList((list) => {
        return [...list, msg];
      });
    }

    socket.on("connect", notifyUserConnected);
    socket.on("user-joined", (list) => updateUserList(list));
    socket.on("user-left", (list) => updateUserList(list));
    socket.on("receive-message", (msg) => updateMessageList(msg));

    return () => {
      socket.off("user-joined");
      socket.off("user-left");
      socket.off("user-sid");
      socket.off("receive-message");
      socket.emit("disconnect-user");
    };
  }, []);


  const sendMessageHandler = (msg: string) => {
    const message: Message = createMessage(msg, activeChat, currSid);
    socket.connect()
    socket.emit("send-message", message);
  };

  return (
    <div className="md:flex justify-center items-start w-[100%] h-[85vh] overflow-hidden">
      <UsersList
        users={onlineUsers.filter((user) => user.sid !== currSid)}
        setActiveChat={(args: User) => {
          setActiveChat(args);
          setInitial(false);
        }}
      />
      {currSid}
      <CommunicationPanel
        messageList={messageList}
        sendMessageHandler={sendMessageHandler}
        chatData={activeChat}
        isInitial={isInitial}
      />
    </div>
  );
}

排查与解决建议

  • 移除重复的socket.connect()调用:客户端初始化时已设置autoConnect: true,组件挂载后socket已建立连接,sendMessageHandler中重复调用connect()会导致连接状态异常,阻塞emit操作。修改后代码:

    const sendMessageHandler = (msg: string) => {
      const message: Message = createMessage(msg, activeChat, currSid);
      socket.emit("send-message", message);
    };
    
  • 添加参数有效性校验:确保sendMessageHandler执行时activeChat不为null、currSid不为空,避免生成无效消息对象:

    const sendMessageHandler = (msg: string) => {
      if (!activeChat || !currSid) return;
      const message: Message = createMessage(msg, activeChat, currSid);
      socket.emit("send-message", message);
    };
    
  • 监听socket错误事件:在useEffect中添加错误监听,排查连接或emit时的异常:

    useEffect(() => {
      // ... 原有代码
      function handleSocketError(error) {
        console.error("Socket错误:", error);
      }
      socket.on("error", handleSocketError);
      
      return () => {
        // ... 原有清理代码
        socket.off("error", handleSocketError);
      };
    }, []);
    
  • 检查服务端消息转发逻辑:取消服务端send-message事件中if (msg.receipient.sid.length === 0) return;的注释,排查是否因接收方sid无效导致消息未转发。

  • 确认socket连接状态:在sendMessageHandler中打印连接状态,验证emit时socket是否处于连接状态:

    const sendMessageHandler = (msg: string) => {
      console.log("Socket连接状态:", socket.connected);
      if (!activeChat || !currSid) return;
      const message: Message = createMessage(msg, activeChat, currSid);
      socket.emit("send-message", message);
    };
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:14:55