NestJS与React Native(Expo)中Socket.IO无法正常通信问题求助
问题分析与解决方案
核心问题在于版本兼容配置缺失、客户端连接实例管理不当以及跨域/网络权限配置遗漏,以下是针对性修复步骤:
1. 修复NestJS网关的CORS配置
React Native属于跨域环境,即使是本地IP连接,也需要显式配置WebSocket网关允许跨域:
import { MessageBody, SubscribeMessage, WebSocketGateway, WebSocketServer } from "@nestjs/websockets"; import { Logger } from "@nestjs/common"; @WebSocketGateway({ cors: { origin: "*", // 开发环境临时用*,生产环境替换为你的移动端域名/IP credentials: true, }, }) export class ChatGateway { private logger = new Logger('ChatGateway'); @WebSocketServer() server; // 添加连接日志,便于排查 handleConnection(client: any) { this.logger.log(`客户端已连接:${client.id}`); } @SubscribeMessage('message') handleMessage(@MessageBody() message: string): void { this.logger.log(`收到消息:${message}`); this.server.emit('message', message); } }
2. 修复React Native客户端的Socket实例管理
原代码在组件顶层创建Socket实例,会导致组件每次渲染都新建连接,引发状态混乱。改用useRef保存实例,并确保仅初始化一次:
import { useState, useEffect, useRef } from 'react'; import { View, Text, TextInput, Button } from 'react-native'; import io from 'socket.io-client'; const ChatScreen = () => { const [message, setMessage] = useState(""); const [receivedMessage, setReceivedMessage] = useState(""); const socketRef = useRef(null); useEffect(() => { // 仅初始化一次Socket连接 socketRef.current = io("http://192.168.1.22:3000", { transports: ["websocket"], forceNew: true, }); const socket = socketRef.current; // 添加错误监听,排查连接异常 socket.on("connect_error", (err) => { console.error("连接错误:", err); }); socket.on("connect", () => { console.log("WebSocket已连接"); }); socket.on("message", (msg) => { setReceivedMessage(msg); }); return () => { socket.disconnect(); }; }, []); // 空依赖,确保仅执行一次 const sendMessage = () => { try { socketRef.current?.emit("message", message); setMessage(""); } catch (error) { console.error("发送消息失败:", error); } }; return ( <View style={{ padding: 20 }}> <Text style={{ marginBottom: 10 }}>收到的消息:{receivedMessage}</Text> <TextInput placeholder="输入消息" value={message} onChangeText={setMessage} style={{ borderWidth: 1, padding: 10, marginBottom: 10 }} /> <Button title="发送" onPress={sendMessage} /> </View> ); }; export default ChatScreen;
3. 配置React Native网络权限
iOS默认禁止明文HTTP连接,Android需要显式开启明文流量,在app.json中添加:
{ "expo": { "ios": { "infoPlist": { "NSAppTransportSecurity": { "NSAllowsArbitraryLoads": true } } }, "android": { "usesCleartextTraffic": true } } }
4. 版本兼容调整(可选)
@nestjs/platform-socket.io@8.4.5依赖的socket.io版本为4.5.x,若上述修复仍无效,可将客户端版本降级到匹配的4.5.4:
npm install socket.io-client@4.5.4
内容的提问来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

