next js loading issues
In the ground since Sat Nov 01 2025
Last watered inSat Nov 01 2025
Related Topics
Referece Links
Next.js Loading State Issues
The Problem
Next.js's App Router introduces a file-based convention for loading states (loading.tsx), but it suffers from fundamental design issues that create poor user experiences, especially when combined with static generation and caching strategies.
What We Experienced
The Scenario
Building a digital garden with:
- Local MDX content
- Static metadata from JSON files
- SSG (Static Site Generation) for topic pages
- generateStaticParams for pre-rendering routes
Expected Behavior
- First visit to /topics/analytics - Page loads (maybe shows loader briefly)
- Navigate away to /topics
- Return to /topics/analytics - Instant navigation from cache, no loader
Actual Behavior
Every navigation showed the loading component (animated flower), even for:
- Previously visited pages
- Statically generated pages
- Pages with no actual data fetching
The Root Causes
Issue 1: loading.tsx Shows on Every Navigation
Even though Next.js claims "loading states are cached and reused on navigation for instant navigation," the reality is different.
When you have loading.tsx in a route segment, Next.js creates a Suspense boundary that triggers on every navigation transition, causing visual flashes even for cached content.
Issue 2: Conflicts with generateStaticParams
GitHub Issue #77322 (Open since 2025)
loading.tsx fundamentally breaks when combined with ISR features:
With app/topics/[topic]/loading.tsx present:
- ❌ Loading state may not appear at all
- ❌ Or appears every time despite pages being pre-rendered
- ❌ No official fix from Next.js team
Issue 3: No Smart Loading States
Next.js forces a binary choice:
Option A: Include loading.tsx
- ✅ Users get feedback if something is slow
- ❌ Shows on every navigation, even cached pages
- ❌ Creates annoying flashes for instant content
Option B: Remove loading.tsx
- ✅ No flashes on cached pages
- ❌ No feedback if something goes wrong
- ❌ Users see blank pages during actual delays
How Other Tools Handle This
React Query
Behavior:
- First visit: Shows loader
- Cached visits: Instant, no loader
- Background refetch: Shows stale data, optional refetch indicator
- Zero configuration needed
SWR (Vercel's Own Library!)
Same smart behavior - only shows loading when actually loading, not on cached data.
The Irony
Vercel created SWR specifically to solve smart caching and loading states, yet Next.js's built-in loading.tsx pattern doesn't have the same intelligence.
Evidence: GitHub Issues
Issue #77322 - loading.tsx with ISR (OPEN)
Status: Unresolved since March 2025 Problem: Using generateStaticParams breaks loading.tsx Impact: 7+ developers affected, no official fix
Quote:
"loading.tsx contents don't appear when using ISR, and removing generateStaticParams makes the loading spinner work but removes cached route benefits"
Issue #43548 - Link Navigation Not Instant
Status: Marked "Completed" but users still report issues Problem: Loading states appear with delay, not instantly Impact: "Navigation creates just horrible experience"
Vercel's Response:
Technical explanation that this is "how it works" - closed without architectural fix
Issue #9989 - Blank Pages on Back Button
Status: Closed (older issue) Problem: Dynamic SSR pages show blank content when using browser back Impact: Production deployments affected
This proves the concern about blank pages without loading.tsx is real, not theoretical.
Issue #54514 - Request to Disable Router Cache
Problem: Router cache revalidates after 30 seconds User Request: Need ability to disable or control cache behavior Status: Ongoing discussion
Why This Matters
For Digital Gardens / Content Sites
Pages with:
- Local content
- No external API calls
- Static generation
Should not need complex loading state management. The content exists at build time and should load instantly.
For Data Fetching Apps
Pages with:
- API calls
- Database queries
- Real async operations
Need smart loading states that:
- Show only when actually waiting
- Don't flash on cached data
- Provide background refetch indicators
Next.js's loading.tsx handles neither case well.
Current Workarounds
1. Remove loading.tsx for SSG Routes
For static pages that load instantly:
Pros:
- No flashing on navigation
- Pages swap instantly
Cons:
- No feedback if something goes wrong
- Relies on SSG always working
2. Use Client Components + React Query
Convert to client-side data fetching:
Pros:
- Smart caching behavior
- No loading flashes on cached data
- Background refetch support
Cons:
- Loses SSR benefits
- More client-side JavaScript
3. Custom Loading Logic
Implement time-based loading states:
Pros:
- Only shows if actually slow
Cons:
- Requires client component
- Extra code for every route
4. Service Worker Workaround (Issue #77322)
One developer created a service worker solution to detect navigation and show loading:
Pros:
- Works with ISR
Cons:
- Complex setup
- Client-side workaround for framework issue
- Maintenance burden
The Design Gap
What Next.js Assumes
- SSG/ISR works perfectly → pages load instantly
- Router Cache works perfectly → subsequent visits instant
- Network is reliable → no delays
- Therefore → loading.tsx as simple fallback is fine
What Reality Requires
- Network can be slow
- Cache can miss or expire
- Prefetch might not complete
- Users need smart feedback, not binary states
What's Missing
- Conditional loading: Show only if actually slow
- Stale-while-revalidate: Show cached content during refetch
- Runtime intelligence: Adapt to actual performance
- Granular control: Per-route caching strategies
Comparison: Next.js vs. Traditional SPA
Traditional SPA (React Router + React Query)
Navigation behavior:
- First load: Shows loader
- Cached: Instant
- No configuration needed
Next.js App Router
Navigation behavior:
- Depends on configuration
- May flash on cached pages
- May show blank on slow loads
- Requires understanding of caching layers
When Next.js Works Well
To be fair, Next.js excels at:
1. Marketing Sites
- Heavily SEO-dependent
- Content changes infrequently
- First load performance critical
- Navigation UX less critical
2. Server-Heavy Apps
- Lots of database queries
- Server-side authorization
- Data that can't be cached client-side
3. ISR-Free Static Sites
- Pure SSG without dynamic params
- Simple page hierarchies
- No complex caching needs
When It Falls Short
1. Interactive Apps
- Client-side state management
- Frequent navigation between pages
- Real-time data updates
- Chat, dashboards, admin panels
2. Content Sites with Dynamic Routes
- Digital gardens
- Documentation sites
- Blogs with category/tag filtering
- Any site using generateStaticParams
3. Apps Requiring Smart Caching
- E-commerce (prices, inventory)
- Social feeds
- Activity streams
- Any data needing stale-while-revalidate
Recommendations
For New Projects
If building:
- Digital garden
- Documentation site
- Blog
- Content-heavy site with dynamic routes
Consider:
- Astro (built for content, zero config routing)
- VitePress (Markdown-first, simple)
- Docusaurus (content-focused)
- Remix (better loading/cache story)
Or traditional SPA:
- Vite + React Router + React Query
- Simple, predictable, smart caching
For Existing Next.js Projects
If experiencing loading issues:
-
Audit your routes:
- Which are truly dynamic (server-rendered)?
- Which are static (can use SSG)?
-
Remove loading.tsx from static routes:
- Pages with generateStaticParams
- Pages reading local files
- Pages with no async operations
-
Keep loading.tsx only for:
- Routes with real database queries
- External API calls
- Server actions with delays
-
Consider React Query for dynamic data:
- Better caching control
- Smart loading states
- Background refetch
Testing Strategy
Always test:
- First navigation to page
- Navigate away
- Return to same page (should be instant)
- Hard refresh and repeat
Watch for:
- Flashing loading states on cached pages
- Blank pages during slow loads
- Inconsistent behavior between navigations
The Bigger Picture
Framework Complexity
Next.js markets itself as "batteries included," but the reality is:
- Multiple caching layers (Server, Data, Router, Full Route)
- File-based conventions that conflict with each other
- Assumptions that don't hold in real-world conditions
- "Solutions" that create new problems
The Trade-off
What you gain:
- SEO-friendly SSR
- Co-located API routes
- Vercel deployment integration
- Edge runtime capabilities
What you pay:
- Complexity managing loading states
- Debugging caching behavior
- Working around framework limitations
- Constant mental model of server/client boundaries
Is It Worth It?
For many apps, especially those that don't need aggressive SEO or server-side rendering, the complexity doesn't pay for itself.
Traditional SPAs with smart client-side caching often provide:
- Better navigation UX
- Simpler mental model
- Fewer edge cases
- More predictable behavior
Conclusion
Next.js's loading.tsx pattern represents a fundamental design gap:
- File-based conventions can't adapt to runtime conditions
- Conflicts with ISR/SSG remain unresolved (Issue #77322)
- No smart caching like React Query or SWR
- Forces binary choice: flash on every navigation OR blank on slow loads
The GitHub issues prove this isn't user error or misconfiguration - it's a known framework limitation that affects production applications.
What Next.js Should Learn From
React Query's Philosophy:
- Runtime intelligence over file conventions
- Stale-while-revalidate by default
- Smart loading states
- Granular cache control
Until Next.js addresses these gaps:
- Be cautious with loading.tsx
- Test navigation behavior thoroughly
- Consider client-side data fetching for better UX
- Don't assume "working as designed" means "good design"
Final Thought
The fact that Vercel created SWR - which solves these problems elegantly - shows they understand smart caching. The question is: when will Next.js learn from its own ecosystem?