next 14 prevent infinite redirects in layout

Hello, I'm creating a chess.com clone - I am attempting to redirect the user if they are currently in a game and they are trying to access any page that is not the 'game page'. Intuitively I thought to do this in a server layout component, so that I can query the serverside game's manager and check if the player is in a game and redirect them if they are. My conditions works, and the user is in fact in a game, they are redirected. However, because they are redirected to a page that is nested within the layout with the redirect condition in, they are redirected again and a redirect cycle begins. How would I go about ensuring that the user is only redirected for this reason once. My initial thought was to do something like if(path !== "/play") redirect("/play") (/play is the page with the game interface on) but I have been having trouble accessing the 'current path' from within the server side layout component. Thanks in advance for any help 🙂
3 Replies
kal
kal•2mo ago
this is my current layout that attempts to redirect the user if they are not in a game. It the 'second top level' layout, and is hosted within a (dynamic) folder, so it runs when any page is loaded.
import { ReactNode } from "react";
import SessionProvider from "~/app/_components/providers/session.provider";
import { TRPCProvider } from "~/app/_components/providers/trpc.provider";
import { getServerSession } from "~/lib/lucia/util.lucia";
import { GameMaster } from "~/lib/game/GameMaster";
import { redirect } from "next/navigation";

export default async function Layout({ children }: { children: ReactNode }) {
const { session, user } = await getServerSession();

if (user && GameMaster.instance().getByPlayer(user.id) !== null)
redirect("/play");

return (
<SessionProvider session={session} user={user}>
<TRPCProvider>
<div>{children}</div>
</TRPCProvider>
</SessionProvider>
);
}
import { ReactNode } from "react";
import SessionProvider from "~/app/_components/providers/session.provider";
import { TRPCProvider } from "~/app/_components/providers/trpc.provider";
import { getServerSession } from "~/lib/lucia/util.lucia";
import { GameMaster } from "~/lib/game/GameMaster";
import { redirect } from "next/navigation";

export default async function Layout({ children }: { children: ReactNode }) {
const { session, user } = await getServerSession();

if (user && GameMaster.instance().getByPlayer(user.id) !== null)
redirect("/play");

return (
<SessionProvider session={session} user={user}>
<TRPCProvider>
<div>{children}</div>
</TRPCProvider>
</SessionProvider>
);
}
Sturlen
Sturlen•2mo ago
I'd suggest not redirecting users unnecessarily. you could instead show a a banner or other indicator with "You are currently in a game. Click here to resume". consider if you were a user and was browsing through the leaderboards on a second tab, would you like having your tab forcibly redirected to the game you already have open on another tab?
kal
kal•2mo ago
That is acctually quite a good thought, I like that approach acctually. Appreciate it, I think that may solve my issue and better user experience all in one, cheers.