[英]Socket IO emit events twice
情況:
我正在設置一個帶有 socket.io 的快速服務器和一個使用 ReactJS 的客戶端。這是我的服務器:
//... another requirement
const socket = require("./socket");
const app = express();
const server = http.createServer(app);
const port = process.env.PORT || 3000;
//... some parsers ...
routes(app);
socket(server);
server.listen(port);
console.log("Server started on: " + port);
這是我的插座:
const socketIO = require("socket.io");
const socket = server => {
const io = socketIO(server);
const chat = io.of("/chat");
chat.on("connection", client => {
console.log("User started chat!");
client.on("disconnect", () => {
console.log("User left chat!");
});
client.on("sendMessage", msg => {
const { id, text } = msg;
console.log(id + " says: " + text);
client.broadcast.emit("incomingMessage", {
//... response data
});
});
});
};
在客戶端中,聊天頁面組件將處理向套接字發送消息和從套接字接收消息:
//_ChatBox in Chat Page
const _ChatBox = (/*props*/) => {
const chat = io("http://localhost" + ":3000/chat");
chat.on("incomingMessage", message => {
console.log("Receive message");
//...handle income message
});
const sendMessageToSocket = (data) => {
chat.emit("sendMessage", data);
};
return ( /*JSX*/);
};
問題:
每次用戶訪問聊天頁面時,套接字都會收到連接事件並記錄User started chat!
控制台一次,但實際上,它記錄了兩次,這意味着套接字已經處理了兩次連接事件。
當 _ChatBox 收到消息時,它會記錄Receive message
並顯示該消息,但它所做的是記錄兩次並顯示消息兩次,這也意味着套接字已發出兩次 incomeMessage 事件。
我想要什么:我希望套接字只處理這些事件一次。
看起來你的組件渲染了兩次,所以調用const chat = io("http://localhost" + ":3000/chat");
兩次,給出兩個連接消息。
您可以使用useEffect()
掛鈎僅在第一次渲染時進行連接。 傳入一個空數組作為第二個參數意味着效果只會被調用一次:
const _ChatBox = (/*props*/) => {
useEffect(()=>{
const chat = io("http://localhost" + ":3000/chat");
chat.on("incomingMessage", message => {
console.log("Receive message");
//...handle income message
});
const sendMessageToSocket = (data) => {
chat.emit("sendMessage", data);
};
}, []);
return ( /*JSX*/);
};
在 index.js 文件中創建套接字並作為道具傳遞給根應用程序組件,如下所示:-
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import socketIOClient from "socket.io-client"
var socket = socketIOClient('http://localhost:9000');
ReactDOM.render(
<React.StrictMode>
<App socket={socket} />
</React.StrictMode>,
document.getElementById('root')
);
現在使用這個套接字來發出這樣的事件:-
import React from "react"
import './App.css';
class App extends React.Component {
componentDidMount() {
this.props.socket.emit('test')
}
render() {
return (
<div>
hello
</div>
);
}
}
export default App;
我有一個類似的問題。 我通過在我的功能組件中編寫一個 useEffect 來解決它,該 useEffect 打開套接字 onMount(和 onUpdate)但關閉 SOCKET ON UNMOUNT。
useEffect(()=>{
const socket = io("http://localhost:3000")
socket.on(userId, (arg) => {
//stuff
});
return () => socket.emit('end'); //Close socket on UNMOUNT
})
我有同樣的問題,我解決了。
return() => {
socket.off("whatever_you_named").off();
}
正如您在此處看到的,您必須使用 React 提供的useEffect
function。 接下來,您必須在useEffect
function 中附加以下代碼,以防止兩次收到相同的消息。 如果您有 4 種監聽方法,則必須將代碼附加 4 次以防止每種方法出現該問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.