I'm working on an app with web socket io and have run into a strange issue. I have a simple app:
import { SocketIOClient } from './containers/SocketIOClient.js';
import { Home } from './screens/Home.js';
import { Game } from './screens/Game.js';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
const App = () => (
<SocketIOClient
router={ (props) => (
<BrowserRouter>
<Routes>
<Route exact path="/" element={<Home {...props} />}></Route>
<Route path="/:lobbyId" element={<Game {...props} />}></Route>
</Routes>
</BrowserRouter>
)}
/>
);
where SocketIOClient just contains the socket client object used to connect to my server. I also have a simple Home page:
import { useState, useEffect } from 'react';
import Container from 'react-bootstrap/Container';
import Button from 'react-bootstrap/Button';
import { useNavigate, useLocation } from 'react-router-dom';
import './Home.css'
export const Home = ({ socket }) => {
const navigate = useNavigate();
const location = useLocation();
const [failedToJoin, setFailedToJoin] = useState(location.state ? location.state.failedToJoin : false);
const createGame = () => {
socket.emit('create_game');
}
useEffect(() => {
socket.on('failed_to_join', () => {
setFailedToJoin(true);
});
socket.on('space_available', ({ lobby_id }) => {
navigate(`/${lobby_id}`);
});
// eslint-disable-next-line
}, [socket])
useEffect(() => {
console.log(navigate)
})
return (
<Container id="home-page">
<Button
variant="info"
onClick={createGame}
>
Create New Game
</Button>
</Container>
);
};
When the user clicks the button, they create a Game and (assuming the space_available message is received) are navigated to:
import { useEffect, useState } from 'react';
import { useParams, useNavigate } from "react-router-dom";
export const Game = ({ socket }) => {
const [joined, setJoined] = useState(false);
const navigate = useNavigate();
const params = useParams();
const lobbyId = params.lobbyId
useEffect(() => {
socket.emit('join_game', { lobby_id: lobbyId, player_id: socket.id })
socket.on('game_joined', _ => {
setJoined(true)
});
socket.on('failed_to_join', () => {
navigate('/', {state: {failedToJoin: true, lobbyId}});
});
return () => {
socket.emit('back_button_pressed', {player_id: socket.id})
}
// eslint-disable-next-line
}, [socket]);
return joined ? (
<div>
<h1>lobby id: {lobbyId}</h1>
</div>
) : null
}
The issue is, if I'm on the Home page and click the Create Game button, I'm brought to the Game page. If I press the browser back button, I go back to the Home page. If I press Create Game again, I'm brought the Game page, but strangely I now have to press the back button 2 times to return to Home.
If I instead press the browser forward button on Home after viewing Game page, I'm given a Warning: Can't perform a React state update on an unmounted component. Does anyone know what's causing me these issues? I have a feeling it's due to the useEffect with the socket working in some way I'm not understanding right.