Working in Next JS environment (App router).
I have a Component (AuthGuard) that wraps all pages in main layout and checks if JWT token is valid in localstorage. Either it allows to render the page or navigate to login screen.
Layout.tsx
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased bg-gray-200`}
>
<ThemeProviders> <-- Suspense added here
<AuthGuard> <-- AuthGuard
<LoaderProvider>
<StoreProvider>
{children}
AuthGuard.tsx
const AuthGuard = ({ children }: PageProps) => {
const { isAuthResolved } = useAuthGuard();
if (!isAuthResolved) return <></>;
return <>{children}</>;
};
useAuthGuard Hook:
export const useAuthGuard = () => {
const router = useRouter();
const currentPath = usePathname();
const searchParams = useSearchParams();
const [isAuthResolved, setIsAuthResolved] = useState(false);
useEffect(() => {
const token = localStorage.getItem("accessToken"); // Retrieve token from local storage
const isValidToken = checkTokenValidity(token);
// If user is not logged in or the token is invalid or expired
if (!token || !isValidToken) {
removeAuthData(); // Clear auth data if invalid
// Redirect to login with redirectTo query parameter
if (currentPath !== ROUTES.LOGIN) {
router.push(
`${ROUTES.LOGIN}?redirectTo=${encodeURIComponent(currentPath)}`
);
}
} else {
// If the user is on the login page and has a valid token, redirect to dashboard
if (currentPath === ROUTES.LOGIN) {
const redirectTo = searchParams.get("redirectTo");
router.push(redirectTo || ROUTES.DASHBOARD);
}
}
setIsAuthResolved(true);
}, [router, currentPath, searchParams, isAuthResolved]);
return { isAuthResolved };
};
The Suspense component is added in ThemeProvider as it is a requirement of useSearchParams hook. App builds fine. Works great in debug mode but when deployed in production environment. I get undefined values for searchParams on page level props.
I am using RTK and on page level searchParams are undefined therefor the API calls are breaking.
Earlier it didn’t have isAuthResolved check, I added that just to not render the component until useSearchParams is resolved. But still it didn’t resolve the issue and searchParams are undefined.
EDIT: Can some one also explain me in their answer why RTK is being triggered if the auth check is not completed yet. Or why props are being undefined.
You are relying on client-side validation, which is not recommended in Next.js. Instead, you should handle redirection to the login page on the server-side component. Additionally, it is better to use cookies for session management rather than local storage.
You can find a complete guide here: Next.js Authentication Documentation.
It would be helpful if you edit your question to clarify how you are storing the token. Are you using a separate server API, or are you relying on Next.js server actions?