javascriptnext.js

Next JS router.push not working without page reload


I'm using Next.js 14.2 with the page directory. When I create a build and run npm start, it opens a landing page with a login button using the <Link> component. I also set prefetch={false} in the login button. When I redirect to the login screen and enter all the correct values, it shows "login successful," but it does not redirect to the dashboard. I'm sharing the redirect code below.

import { useRouter } from 'next/router';
const router = useRouter();

useEffect(() => {
   if (loggedin && localStorage?.getItem('token')) {
     console.log("isReady", router.isReady);
     router.push(ROUTE_NAMES.DASHBOARD);
   }
 }, [loggedin]);

When I check the console, isReady is returning true. Let me know where I'm wrong.

EDIT

I change a bit and put a condition of isReady state when changing the route. But when i set the middleware I got stuck again it is not changing page.

  if (NO_AUTH_ROUTES.includes(pathname)) {
    return NextResponse.next();
  } else if (isAuthenticate && AUTH_ROUTES.includes(pathname)) {
    // Return to dashboard as it is in auth route
    return NextResponse.redirect(new URL(ROUTE_NAMES.DASHBOARD, request.url));
  } else if (!AUTH_ROUTES.includes(pathname)) {
    // Check if the pathname is not in AUTH_ROUTES
    // If token or isAuthenticate is missing, redirect to login
    if (!isAuthenticate) {
      return NextResponse.redirect(new URL(ROUTE_NAMES.LOGIN, request.url));
    }
  }
  return NextResponse.next();

Solution: github.com/vercel/next.js/discussions/51782


Solution

  • You might encounter an issue where router.push() in Next.js doesn't redirect the user as expected after successful authentication when called from middleware. A potential fix for this is to refresh the router just before invoking router.push(). This seems to solve the issue, though the exact reason behind it isn't well-documented.

    Here’s a code example:

    // After successful authentication
    router.refresh(); // Refresh the router state
    router.push('/desired-url'); // Redirect the user to the desired URL

    By calling router.refresh(), you force the router to update its state, which ensures that router.push() works as intended. This approach worked for me, and I hope it helps others facing the same issue.

    Reference: https://github.com/vercel/next.js/discussions/51782#discussioncomment-6470680