Не работает SocketIO на клиентской части(react)
Пишу Клиент-серверное приложение на express-js, reactjs. Мне нужно добавить real time. Задача сделать timer для всех пользователей одинаковым + liveChat. Решил начать с начального и сразу застрял.
Серверная часть:
const express = require('express');
const PORT = process.env.PORT || 5050;
const userRouter = require('./routes/user.routes');
const gameRouter = require('./routes/game.routes');
const cors = require('cors');
const http = require('http');
const { Server } = require("socket.io");
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"]
}
});
io.on('connection', (socket) => {
console.log('Новое подключение', socket.id);
socket.on('message:created', (message) => {
console.log('Новое сообщение', message);
});
});
const corsOptions = {
origin: '*',
methods: "*",
allowedHeaders: "*"
};
app.use(cors(corsOptions));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use('/api', userRouter);
app.use('/game', gameRouter);
server.listen(PORT, () => console.log(`Cтарутем на порту ${PORT}`));
часть кода с клиента (react)
import React, { useState, useEffect, useRef } from "react";
import './FirstGame.css'
import io from 'socket.io-client';
const socket = io('http://localhost:5050', { transports: ['websocket'] });
const FirstGame = () => {
const [countdown, setCountdown] = React.useState(11);
const [currentPage, setCurrentPage] = React.useState(1);
const itemsPerPage = 10;
const startCountdown = () => {
let timer = 11;
const timerInterval = setInterval(() => {
timer--;
setCountdown(timer);
if (timer === 0) {
clearInterval(timerInterval);
}
}, 1000);
return () => {
clearInterval(timerInterval);
};
};
const socketRef = useRef(null);
useEffect(() => {
socketRef.current = socket;
socket.on("connect", () => {
console.log("Соединение установлено", socket.id);
});
socket.on("disconnect", () => {
console.log("Соединение разорвано");
});
return () => {
socket.disconnect();
};
}, []);
при запуске сервера, отрабатывают все логи, 1 лог. порт, 2 лог. Новое подключение с socket.id. На клиенте при открытии страницы или перезагрузки срабатывает лог: Соединение разорвано. Хотя на сервере каждый раз отрабатывает новое подключение с новым socket.id.
Ответы (1 шт):
Реакт, начиная с 18 версии в строгом режиме <React.StrictMode>
в режиме разработки выполняет установку всех компонентов дважды.
В случае с вашим кодом вне компонента происходит инициализация сокета и устанавливается соединение, далее компонент устанавливается(первый раз).
Затем компонент размонтируется и соединение по сокету разрывается и компонент устанавливается повторно(но соединение уже разорвано)
Исправить такое поведение можно, перенеся установку соединения по сокету в useEffect
useEffect(() => {
const socket = io('http://localhost:5050', { transports: ['websocket'] });
socketRef.current = socket;
socket.on("connect", () => {
console.log("Соединение установлено", socket.id);
});
socket.on("disconnect", () => {
console.log("Соединение разорвано");
});
return () => {
socket.disconnect();
};
}, []);
Либо так, сразу при инициализации компонента
const [socket, setSocket] = React.useState(io('http://localhost:5050', { transports: ['websocket'] }));