React前端无法接收后端Socket.io发送的信号求助
Socket.io 聊天应用:前端无法接收后端发出的信号
我学习Socket.io后搭建了一个全局聊天应用,前后端已完成,但React前端无法接收后端Socket.io发送的信号。经检查,后端能正常接收前端发送的信号,但前端收不到后端返回的信号。以下是相关代码:
服务端index.js
import express from 'express'; import cors from 'cors'; import http from 'http'; import dt from 'dotenv'; import {Server} from 'socket.io'; import userRoutes from './routes/userRoutes.js'; import {dbConnect} from './config/db.js' import {errorHandler} from './middlewares/errorMiddleware.js' const dotenv = dt.config(); import MSG from './models/messageModel.js'; const PORT = process.env.NODE_PORT || 5000; const app = express(); app.use(express.urlencoded({extended : false})); app.use(express.json()); app.use(cors()); const server = http.createServer(app); dbConnect(); const io = new Server(server, { cors : { origin : "http://localhost:5173", methods : ["GET","POST"] } }); io.on('connection', (socket) => { socket.on('conn_made', async() => { const messages = await MSG.find(); socket.emit('initload', {msg : messages}); }) socket.on('post', async(data) => { const message = await MSG.create(data); socket.emit('updatemsg', message); }) }); app.use('/api/user', userRoutes); app.use(errorHandler); server.listen(PORT, () => { console.log(`The Server is running on ${PORT}`); });
Redux切片代码
import { createSlice } from "@reduxjs/toolkit"; import io from 'socket.io-client'; const socket = io.connect('http://localhost:8000/'); const initState = { messages : [], isLoading : false } export const messageSlice = createSlice({ name : 'message', initialState : initState, reducers : { resetmsg : (state) => { state.messages = []; state.isLoading = false; }, addInit : (state,action) => { state.isLoading = false; console.log(action.payload); }, connect : (state) => { socket.emit('conn_made'); state.isLoading = true; }, post : (state,action) => { socket.emit('post', action.payload); }, receive : (state,action) => { state.messages.push(action.payload); } } }); export const {resetmsg,addInit,connect,post,receive} = messageSlice.actions; export default messageSlice.reducer;
前端Mainchat组件代码
import React, { useState, useEffect } from 'react'; import {FaSignOutAlt, FaShare} from 'react-icons/fa'; import {logout} from '../features/auth/authSlice'; import { useNavigate } from 'react-router-dom'; import {useSelector, useDispatch} from 'react-redux'; import io from 'socket.io-client'; const socket = io.connect('http://localhost:8000/'); import {resetmsg , addInit , connect , post , receive } from '../features/messages/messageSlice'; const Mainchat = () => { const [connected, setConnected] = useState(false); const [text, setText] = useState(""); const {user} = useSelector((state) => state.auth); const dispatch = useDispatch(); const navigate = useNavigate(); socket.on('initload', (data) => { const {msg} = data; dispatch(addInit(msg)); }) socket.on('updatemsg', (data) => { dispatch(receive(data)); }) const handleConnect = () => { dispatch(connect()); setConnected(true); } const handleLogout = async () => { await dispatch(logout()); dispatch(resetmsg()); navigate('/login'); } const onSend = () => { const msg = {user : user._id , text : text}; dispatch(post(msg)) setText(""); } return ( <section className='container flex flex-col p-4 mt-16 h-full w-[40vw] border-2 border-gray-300 rounded-lg'> <div className='flex flex-row justify-between mb-5'> <h1 className='text-3xl font-bold'>{connected ? "Connected." : "Disconnected."}</h1> <button onClick={handleLogout}><FaSignOutAlt /></button> </div> {connected ? ( <div className='flex flex-col space-y-2'> <div className='h-[400px] border-y-2 overflow-y-scroll'> </div> <div className='flex flex-row justify-between'> <input value={text} onChange={(e) => setText(e.target.value)} className='w-96 border-2 border-black py-1 px-2 rounded-lg' type='text' placeholder='Type your Message...' /> <button onClick={onSend}><FaShare/></button> </div> </div> ) : ( <button onClick={handleConnect}>Connect</button> )} </section> ) } export default Mainchat
问题排查与解决方案
1. 端口不匹配(核心问题)
后端默认运行在5000端口(PORT = process.env.NODE_PORT || 5000),但前端Redux切片和组件里都连接的是http://localhost:8000/,端口不一致导致前端无法接收到后端消息。
修复:将前端所有io.connect的地址改为http://localhost:5000/,或者修改后端端口为8000。
2. 重复创建Socket实例
Redux切片和Mainchat组件各自创建了独立的Socket连接:
- 点击Connect时,Redux里的Socket发送了
conn_made事件 - 但Mainchat组件里的另一个Socket在监听
initload和updatemsg,两个Socket不属于同一个连接,因此组件监听器收不到返回消息。
修复:创建共享Socket实例,统一管理:
// src/utils/socket.js import io from 'socket.io-client'; const socket = io.connect('http://localhost:5000/'); export default socket;
然后在Redux切片和组件中导入该实例:
// Redux切片 import socket from '../utils/socket'; // Mainchat组件 import socket from '../utils/socket';
3. 组件监听器内存泄漏优化
在组件卸载时移除Socket监听器,避免内存泄漏:
useEffect(() => { const handleInitLoad = (data) => { const {msg} = data; dispatch(addInit(msg)); }; const handleUpdateMsg = (data) => { dispatch(receive(data)); }; socket.on('initload', handleInitLoad); socket.on('updatemsg', handleUpdateMsg); return () => { socket.off('initload', handleInitLoad); socket.off('updatemsg', handleUpdateMsg); }; }, [dispatch]);
内容的提问来源于stack exchange,提问作者roverrr
相关产品推荐
相关产品推荐

