NextJS Redirect Without Flashing Content
Jasser Mark Arioste
Hello hustlers. In this tutorial, you'll learn how to use a server-side redirect to prevent the flashing of content for unauthenticated users. We'll use NextJS Middleware along with the next-auth package for authentication.
Prerequisites #
This guide assumes the following:
- You're using NextJS v12.3.4 and above. This gives us the best middleware functionality.
- You're using next-auth v4.17 and above.
Problem with Static Pages #
If you're using next-auth and you have static pages in your app, you can only get the session from the client-side. Sometimes, this creates a delay in getting the user and shows flashing content if not implemented properly:
import { NextPage } from "next"; import { signOut, useSession } from "next-auth/react"; import React from "react"; const HomePage: NextPage = () => { const { data } = useSession(); if (!data?.user) { return <div>Unauthorized - 403. Please login</div>; } return ( <div> <h1>Home Page</h1> <p>You are logged in as {data?.user?.email} </p> </div> ); }; export default HomePage;
12345678910111213141516
Another problem with this approach is that we have to add this logic to every page that needs authentication.
This flashing doesn't occur in server-side generated pages since we can check the session inside getServerSideProps
and redirect to the login page as necessary:
Inside a page component:
// pages/admin.tsx import { GetServerSideProps } from "next"; import { getSession, useSession } from "next-auth/react"; import { GetServerSideProps } from "next"; import { getSession, useSession } from "next-auth/react"; import React from "react"; const AdminPage = () => { const { data } = useSession(); if (!data?.user) { return <div>Unauthorized - 403. Please login</div>; } return <div>AdminPage</div>; }; export default AdminPage; export const getServerSideProps: GetServerSideProps = async (ctx) => { const session = await getSession({ req: ctx.req }); if (!session) { return { redirect: { destination: "/login", permanent: false, }, }; } return { props: { session, }, }; };
12345678910111213141516171819202122232425262728293031
Inside _app.tsx
:
import "../styles/globals.css"; import type { AppProps } from "next/app"; import { SessionProvider } from "next-auth/react"; function MyApp({ Component, pageProps }: AppProps) { const { session, ...restPageProps } = pageProps; return ( <SessionProvider session={session}> <Component {...restPageProps} /> </SessionProvider> ); } export default MyApp;
1234567891011121314
This prevents flashing the unauthorized content since the session is provided via props
and the client does not have to make a request using /api/auth/session
. The problem with this approach is that, you'll have to add this logic for every protected page in your application.
How can we improve on this?
The Solution #
Since NextJS v12+, we have the ability to process the incoming request before returning the generated page (static or server-side generated).
Create a middleware.ts
file at the root directory of your project and add this logic here:
// middldware.ts import { getToken } from "next-auth/jwt"; import { NextRequest, NextResponse } from "next/server"; export async function middleware(req: NextRequest) { const pathname = req.nextUrl.pathname; const protectedPaths = ["/", "/admin"]; const isPathProtected = protectedPaths?.some((path) => pathname == path); const res = NextResponse.next(); if (isPathProtected) { const token = await getToken({ req }); if (!token) { const url = new URL(`/login`, req.url); url.searchParams.set("callbackUrl", pathname); return NextResponse.redirect(url); } } return res; }
12345678910111213141516171819
Demo and Code #
Conclusion #
We learned how to redirect without flashing content by using NextJS middleware. Middleware is a very powerful feature in NextJS and there's a lot we can do to process the incoming request.
If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on Twitter.
What's Next? #
- Add role-based authorization for your NextJS app. Differentiate normal users from admin users and what pages they can access.
- Implement middleware chaining/stacking. Organize your middleware functions like a pro.