how to use useParams() inside of useEffect

Advertisements

I want to load different components on component mount based on the URL params but my useParams() object room is showing as undefined in my useEffect() for some reason.

// App.js
function App() {
  const { room } = useParams();
  const [inGame, setInGame] = useState(false);

  useEffect(() => {
    console.log(room); // undefined

    socket.emit("am_i_in_game", room, (res) => {
      setInGame(res.inGame);
      return;
    });

    return;
  }, [room]);

  return (
    <ThemeProvider theme={darkTheme}>
        <Routes>
          <Route
            path="/:room" 
            element={
              inGame ? <GameScreen {...gameScreenProps} />
              : room?.length === 6 ? (
                <StartScreen {...{
                  ...startScreenProps, 
                  hasJoinEmbed: true
                }} />
              ) : <StartScreen {...startScreenProps} />
            } 
          />
        </Routes>
    </ThemeProvider> 
  );

>Solution :

The App component can’t read a route path parameter from a route rendered below itself.

I suggest creating a Room component that is rendered on path="/:room" and can read the room route path parameter and issue the side-effect and render the appropriate content. Basically move the state and logic in App down the ReactTree.

Example:

const Room = () => {
  const { room } = useParams();
  const [inGame, setInGame] = useState(false);

  useEffect(() => {
    console.log(room);

    socket.emit("am_i_in_game", room, (res) => {
      setInGame(res.inGame);
      return;
    });
  }, [room]);

  return inGame
    ? <GameScreen {...gameScreenProps} />
    : (
      <StartScreen
        {...startScreenProps}
        hasJoinEmbed={room?.length === 6}
      />
    );
};
function App() {
  return (
    <ThemeProvider theme={darkTheme}>
      <Routes>
        <Route path="/:room" element={<Room />} />
      </Routes>
    </ThemeProvider> 
  );
}

Leave a ReplyCancel reply