Добрый день.
В SPA приложении я подключаю пользователя к сокету, как только он будет авторизован
useEffect(() => {
if (isAuth) {
dispatch(
SocketActionCreators.setSocket(
io(API_URL, {
transports: ['websocket'],
path: '/server',
})
)
);
} else if (socket && !isAuth) {
socket.disconnect();
}
}, [isAuth]);
На страницах мероприятия (socket room, по факту) я подключаю его к комнате и регистрирую обработчики и тд
useEffect(() => {
if (socket) {
socket.emit('user:join-webinar', { user, webinarId });
socket.on('users:get', (rosters) => {
dispatch(CurrentWebinarActionCreators.setRosters(rosters));
});
socket.emit('message:get', webinarId);
socket.on('messages', (messages) => {
dispatch(CurrentWebinarActionCreators.setMessages(messages));
});
socket.on('chat:status', (status) => {
dispatch(CurrentWebinarActionCreators.setChatIsAvailable(status));
});
return () => {
socket.emit('user:left-webinar', { user, webinarId });
};
}
}, [webinarId, socket]);
Проблема в следующем: на странице мероприятия мне как-то надо показывать пользователю, что произошла потеря соединения, что оно будет восстановлено, как только связь появится.
для этого в последнем useEffect-е я добавил:
// переменная для предотвращения показа сообщения о восстановлении связи
// при первом подключении
let firstConnection = true;
socket.on('connect', () => {
if (!firstConnection) {
message.success({
content: 'Связь восстановлена',
key: 'updatable',
duration: 2,
});
}
});
socket.on('disconnect', () => {
firstConnection = false;
message.error({
content: 'Потеря соединения',
key: 'updatable',
duration: 2,
}).then(() =>
message.loading({
content: 'Пытаемся восстановить подключение...',
key: 'updatable',
duration: 0,
})
);
});
все нормально, но есть три проблемы:
1) эти обработчики сработают на других страницах после размонтирования этого компонента (в целом, понятно, почему). я пытался их удалить так:
socket.removeAllListeners(["connect", "disconnect"]), но это не работает, работает только удаление всех
socket.removeAllListeners() - это не выход... как можно оповещать пользователя только на данной странице ?
2) после возобновления связи с сервером подключение с сокетом восстанавливается, но к комнате пользователь не присоединится до перезагрузки страницы, т.к. у меня для этого отдельный emit:
socket.emit('user:join-webinar', { user, webinarId }). Можно ли как-то сделать это автоматически?
3) как можно разрывать соединение на старой вкладке, если пользователь пытается открыть несколько копий страницы?