nextjs - 💡(How to fix) Fix router.push triggers full page reload instead of soft navigation with output: 'export' in Next.js 16.2.1 [1 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#91934Fetched 2026-04-08 01:30:01
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Timeline (top)
closed ×1commented ×1labeled ×1locked ×1

Code Example

const nextConfig = {
  output: 'export',
  trailingSlash: true,
  reactStrictMode: true,
  images: { unoptimized: true },
  reactCompiler: true,
};

---

router.push called at T+0ms  → URL: /items/?listId=abc&itemId=456
beforeunload fired at T+35ms → URL still: /items/?listId=abc&itemId=123 (original)
RAW_BUFFERClick to expand / collapse

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

  • Next.js: 16.2.1 (works correctly on 16.1.6)
  • React: 19
  • Node.js: 24.3.0
  • OS: macOS (Darwin 25.3.0)
  • Build: Static export (output: 'export')
  • Serving: serve out -l 3000

next.config.js

const nextConfig = {
  output: 'export',
  trailingSlash: true,
  reactStrictMode: true,
  images: { unoptimized: true },
  reactCompiler: true,
};

Describe the Bug

After upgrading from Next.js 16.1.6 to 16.2.1, router.push() triggers a full page reload (MPA navigation) instead of a client-side soft navigation when:

  1. Using output: 'export' (static export)
  2. Navigating to the same pathname with different search params
  3. It is the first navigation after a hard reload

Subsequent navigations work correctly as soft navigations.

Steps to Reproduce

  1. Build a static export app with output: 'export' and trailingSlash: true
  2. Serve the output with a static file server (e.g., serve out)
  3. Navigate to a page like /items/?listId=abc&itemId=123
  4. Hard reload the page (Cmd+R)
  5. Trigger a router.push('/items/?listId=abc&itemId=456') (same path, different search params)
  6. Expected: Client-side soft navigation occurs, URL updates, components re-render
  7. Actual: Full page reload occurs (beforeunload fires, JavaScript context is lost)

Evidence from debugging

Using sessionStorage to persist data across the reload, we captured the following timeline:

router.push called at T+0ms  → URL: /items/?listId=abc&itemId=456
beforeunload fired at T+35ms → URL still: /items/?listId=abc&itemId=123 (original)
  • history.pushState was never called — the router fell through to MPA navigation
  • location.assign and location.replace were not called — the reload is triggered internally by Next.js
  • The beforeunload stack trace points to Next.js internal router code
  • performance.getEntriesByType('navigation') reports type: "navigate" after the reload

Additional context

  • The issue does not occur with Next.js 16.1.6 (same codebase, same config)
  • The issue does not occur in next dev mode — only in production static export
  • reactCompiler: true was tested and is not related (issue persists with it disabled)
  • scroll: false option on router.push does not prevent the issue
  • Only the first router.push after a hard reload triggers the full reload; subsequent navigations work fine

Which area(s) are affected?

  • App Router
  • Static Export (output: 'export')

extent analysis

Fix Plan

To fix the issue with router.push() triggering a full page reload in Next.js 16.2.1, we need to modify the next.config.js file and add a custom getStaticPaths function to handle the static export correctly.

  • Update next.config.js to include the following code:
module.exports = {
  // ... existing config ...
  experimental: {
    // Add this option to enable the fix
    appDir: true,
  },
}

However, since the issue is related to the static export and the router.push() behavior, we can try to override the default behavior by using the useRouter hook from next/router and manually handling the navigation.

  • Create a custom hook to handle the navigation:
// useCustomRouter.js
import { useRouter } from 'next/router';
import { useEffect } from 'react';

const useCustomRouter = () => {
  const router = useRouter();

  const customPush = (url, as) => {
    // Check if the URL is the same but with different search params
    if (url === router.asPath.split('?')[0] && as === url) {
      // Manually update the URL and trigger a re-render
      window.history.pushState({}, '', url);
      router.replace(url, as, { shallow: true });
    } else {
      // Default behavior
      router.push(url, as);
    }
  };

  return customPush;
};

export default useCustomRouter;
  • Use the custom hook in your components:
// MyComponent.js
import useCustomRouter from '../useCustomRouter';

const MyComponent = () => {
  const customPush = useCustomRouter();

  const handleNavigation = () => {
    customPush('/items/?listId=abc&itemId=456', '/items/?listId=abc&itemId=456');
  };

  return (
    <div>
      <button onClick={handleNavigation}>Navigate</button>
    </div>
  );
};

Verification

To verify that the fix worked, follow these steps:

  • Build and serve the application using the updated next.config.js file.
  • Navigate to a page like /items/?listId=abc&itemId=123.
  • Hard reload the page (Cmd+R).
  • Trigger a router.push('/items/?listId=abc&itemId=456') (same path, different search params).
  • Check if the URL updates correctly and the components re-render without a full page reload.

Extra Tips

  • Make sure to test the fix in different scenarios and environments to ensure it works as expected.
  • If you encounter any issues or regressions, consider opening a new issue or seeking help from the Next.js community.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING