nextjs - ✅(Solved) Fix Bug: App Router renders incorrect page and refreshes when navigating with basePath (Next.js 16) [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#90540Fetched 2026-04-08 00:19:56
View on GitHub
Comments
2
Participants
2
Timeline
4
Reactions
0
Author
Participants
Assignees
Timeline (top)
commented ×2assigned ×1issue_type_added ×1

PR fix notes

Fix: Same-Route Navigation Causes Page Flash and Metadata Flicker (Next.js 16 App Router + basePath)

Problem

When clicking a <Link> that points to the current active route, Next.js 16 App Router incorrectly triggers a navigation event instead of a no-op. This causes:

  • A brief flash of unrelated page content (served from router cache)
  • Incorrect metadata rendered during the flash
  • A full client-side navigation cycle on an already-active route

This behavior is only present when basePath is configured in next.config.js. Removing basePath resolves the issue.


Root Cause

The router cache key resolution does not correctly account for basePath when comparing the current route against the target href. As a result:

  • pathname === href evaluates to false (path mismatch due to basePath prefix)
  • Navigation proceeds instead of being suppressed
  • A stale cache entry for a different route is momentarily rendered before the correct page re-hydrates

Workaround

Option 1: Suppress navigation when already on the same route (Recommended)

Wrap <Link> with an onClick guard that prevents re-navigation:

"use client"

import Link from "next/link"
import { usePathname } from "next/navigation"

interface SafeLinkProps extends React.ComponentProps<typeof Link> {
  href: string
}

export function SafeLink({ href, children, onClick, ...props }: SafeLinkProps) {
  const pathname = usePathname()

  const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
    if (pathname === href) {
      e.preventDefault()
      return
    }
    onClick?.(e)
  }

  return (
    <Link href={href} onClick={handleClick} {...props}>
      {children}
    </Link>
  )
}

Replace <Link> with <SafeLink> in your category nav:

// Before
<Link href="/menu/pizza">Pizza</Link>

// After
<SafeLink href="/menu/pizza">Pizza</SafeLink>

Option 2: Disable router cache for affected segments

In the affected page or layout, opt out of client-side caching to prevent stale cache entries from flashing:

// app/menu/[category]/page.tsx
export const dynamic = "force-dynamic"

Note: This increases server load — use only on pages where the flash is most visible.


Option 3: Stabilize metadata with generateMetadata

Prevent metadata from flickering during the flash by ensuring it resolves server-side:

// app/menu/[category]/page.tsx
export async function generateMetadata({
  params,
}: {
  params: { category: string }
}) {
  return {
    title: `${params.category} — Menu`,
  }
}

Avoid deriving metadata client-side (e.g. in useEffect) as it will update after hydration and contribute to the flicker.


Option 4: Remove or scope basePath (if feasible)

If basePath is not strictly required, removing it eliminates the root cause entirely:

// next.config.js
module.exports = {
  // basePath: "/app",  // remove or scope to non-affected routes
}

Verification

After applying Option 1:

  1. Navigate to /menu/pizza
  2. Click the Pizza link again
  3. Confirm:
    • No page flash occurs
    • Metadata remains stable
    • Network tab shows no new navigation request

Environment

FieldValue
Next.js16.x
React19
RouterApp Router
Affected areacacheComponents
TriggerbasePath enabled in next.config.js
Repro100% in dev and production

References

Suggested Upstream Fix

The router's same-route detection logic should strip basePath before comparing pathname to the target href, consistent with how usePathname() already returns the path without the basePath prefix.

Code Example

Next.js: 16.x
React: 19
App Router
Browser: Chrome (latest)


Occurs in both dev and production builds
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/alexismendez11/ecommerce-demo

To Reproduce

  1. Open the demo site.
  2. Navigate to a category page (example: Pizza).
  3. While already on the Pizza category page, click the Pizza link again.
  4. Observe the behavior.

Current vs. Expected behavior

Current behavior

  • The page performs a refresh/navigation even though the route is the same.
  • For a brief moment, content from a different category/page is rendered.
  • Then the correct Pizza page renders again.
  • The flashed page is not the previous page nor the destination — it appears to come from router cache.
  • Metadata also briefly changes during this flash.

Expected behavior

  • When clicking a <Link> pointing to the current route:
  • No navigation should occur.
  • No refresh should happen.
  • No other page content should render.
  • Metadata should remain stable.

Provide environment information

Next.js: 16.x
React: 19
App Router
Browser: Chrome (latest)


Occurs in both dev and production builds

Which area(s) are affected? (Select all that apply)

cacheComponents

Which stage(s) are affected? (Select all that apply)

next start (local)

Additional context

Demo site

Summary

When using App Router with basePath enabled in Next.js 16, client navigation sometimes:

  • briefly renders content from an unrelated page
  • updates metadata incorrectly
  • refreshes even when navigating to the same route

This behavior does not occur when basePath is removed.

extent analysis

Fix Plan

Disable basePath in next.config.js

basePath can cause unexpected behavior when using client navigation. To fix the issue, disable basePath in your next.config.js file.

module.exports = {
  // ...
  basePath: false, // Disable basePath
  // ...
}

Use useClient with Link component

To prevent unexpected navigation, use the useClient hook with the Link component.

import Link from 'next/link';
import { useClient } from 'next/navigation';

function CategoryPage() {
  const client = useClient();

  return (
    <div>
      <h1>Pizza</h1>
      <Link href="/menu/pizza" passHref={true} useClient={client}>
        <a>Pizza</a>
      </Link>
    </div>
  );
}

Verify the fix

  1. Open the demo site.
  2. Navigate to a category page (example: Pizza).
  3. While already on the Pizza category page, click the Pizza link again.
  4. Observe the behavior. The page should not refresh or render content from an unrelated page.

Extra Tips

  • Make sure to remove basePath from your next.config.js file to prevent any potential issues.
  • Use useClient with Link component to prevent unexpected navigation.
  • If you're using basePath for a specific reason, consider using a different approach to achieve the same result.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

  • When clicking a <Link> pointing to the current route:
  • No navigation should occur.
  • No refresh should happen.
  • No other page content should render.
  • Metadata should remain stable.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING