Bird
Raised Fist0
NextJSframework~15 mins

Shallow routing concept in NextJS - Deep Dive

Choose your learning style10 modes available
Overview - Shallow routing concept
What is it?
Shallow routing in Next.js is a way to change the URL in the browser without running data fetching methods or reloading the page completely. It updates the path or query parameters but keeps the current page component mounted. This helps create faster and smoother user experiences by avoiding unnecessary page reloads.
Why it matters
Without shallow routing, every URL change causes the whole page to reload or fetch data again, which can slow down the app and make it feel less responsive. Shallow routing lets developers update the URL to reflect state changes or filters without interrupting the user's interaction. This makes web apps feel more like native apps, improving user satisfaction and performance.
Where it fits
Before learning shallow routing, you should understand basic Next.js routing and how pages and URLs work. After mastering shallow routing, you can explore advanced client-side navigation techniques, dynamic routing, and state management tied to URLs.
Mental Model
Core Idea
Shallow routing changes the URL without fully reloading the page or fetching new data, keeping the current page state intact.
Think of it like...
It's like changing the channel number on your TV remote without turning the TV off and on again; the screen updates smoothly without interruption.
┌─────────────────────────────┐
│ User clicks a link or action│
└─────────────┬───────────────┘
              │
      ┌───────▼────────┐
      │ Shallow routing │
      └───────┬────────┘
              │
┌─────────────▼─────────────┐
│ URL changes in browser bar │
│ Page component stays alive │
│ No data fetching rerun     │
└────────────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Next.js Routing Basics
🤔
Concept: Learn how Next.js handles page navigation and URL changes by default.
Next.js uses file-based routing where each file in the pages folder becomes a route. When you navigate to a new URL, Next.js loads the new page component and runs data fetching methods like getServerSideProps or getStaticProps. This reloads the page content fully.
Result
Navigating to a new URL reloads the page and fetches new data.
Understanding default routing behavior is essential to see why shallow routing improves performance by avoiding full reloads.
2
FoundationWhat Happens on URL Change Normally
🤔
Concept: Explore the full page reload and data fetching triggered by URL changes.
When you click a link or use router.push in Next.js, the framework fetches the new page's data and replaces the current page component. This ensures fresh content but can cause delays and lose current page state like scroll position or form inputs.
Result
Page reloads and data fetching happen on every URL change.
Knowing this default helps appreciate how shallow routing avoids these costly operations.
3
IntermediateIntroducing Shallow Routing in Next.js
🤔Before reading on: do you think shallow routing reloads the page or keeps it intact? Commit to your answer.
Concept: Shallow routing updates the URL without running data fetching methods or remounting the page component.
Next.js router.push and router.replace accept an option { shallow: true }. When used, Next.js changes the URL but does not call getServerSideProps, getStaticProps, or getInitialProps again. The current page component stays mounted, preserving state.
Result
URL changes but page content and state remain unchanged.
Understanding shallow routing's option unlocks smoother navigation and better user experience.
4
IntermediateUsing Shallow Routing with Query Parameters
🤔Before reading on: do you think shallow routing works only for path changes or also for query parameters? Commit to your answer.
Concept: Shallow routing is especially useful for updating query parameters without full reloads.
You can change query strings like filters or pagination using shallow routing. For example, router.push({ pathname: '/products', query: { page: 2 } }, undefined, { shallow: true }) updates the URL to show page 2 but keeps the product list component mounted without refetching data.
Result
URL query updates smoothly, and UI can react without full reload.
Knowing shallow routing works with queries helps build dynamic, responsive interfaces.
5
AdvancedHandling State and Effects with Shallow Routing
🤔Before reading on: do you think shallow routing automatically updates component data or do you need to handle it manually? Commit to your answer.
Concept: Shallow routing changes URL but does not automatically update component state or fetch new data.
When using shallow routing, you must listen to route changes (e.g., with useEffect on router.query) and update component state manually if needed. This gives you control but requires careful handling to keep UI in sync with URL.
Result
Component state updates only if you handle route changes explicitly.
Understanding this prevents bugs where UI and URL get out of sync after shallow routing.
6
AdvancedLimitations and Edge Cases of Shallow Routing
🤔
Concept: Learn when shallow routing does not work or causes unexpected behavior.
Shallow routing only works within the same page component. Changing to a different page always triggers full reload. Also, some Next.js features like middleware or server-side redirects ignore shallow routing. Complex state tied to URL may need extra synchronization logic.
Result
Shallow routing is limited to same-page URL changes and requires careful use.
Knowing these limits helps avoid misuse and choose the right navigation method.
7
ExpertOptimizing Performance with Shallow Routing
🤔Before reading on: do you think shallow routing always improves performance or can it sometimes cause issues? Commit to your answer.
Concept: Shallow routing can improve performance but must be used wisely to avoid stale data or confusing UX.
In production, shallow routing is combined with client-side data fetching libraries like SWR or React Query to update data on demand. This avoids full page reloads while keeping data fresh. Also, developers use shallow routing to preserve scroll position and form inputs during navigation, enhancing UX.
Result
Apps feel faster and smoother with controlled data updates and preserved UI state.
Understanding how shallow routing fits into a full data and UI strategy is key for expert-level app optimization.
Under the Hood
Next.js uses the HTML5 History API to change the browser URL without reloading the page. When shallow routing is enabled, Next.js skips calling data fetching methods and does not unmount the current page component. Instead, it updates the router state internally and triggers route change events with a shallow flag, allowing components to react if needed.
Why designed this way?
Shallow routing was designed to improve user experience by avoiding unnecessary page reloads and data fetching when only minor URL changes occur. This design balances between full navigation and client-side state updates, giving developers control over when to reload data. Alternatives like full reloads were too slow, and fully client-side routing lacked integration with Next.js data fetching.
┌───────────────┐
│ User triggers │
│ URL change    │
└───────┬───────┘
        │
┌───────▼─────────────┐
│ Next.js router.push  │
│ with { shallow: true }│
└───────┬─────────────┘
        │
┌───────▼─────────────┐
│ History API updates  │
│ browser URL         │
└───────┬─────────────┘
        │
┌───────▼─────────────┐
│ Skip data fetching   │
│ Keep page component  │
│ mounted              │
└───────┬─────────────┘
        │
┌───────▼─────────────┐
│ Trigger route change │
│ event with shallow  │
│ flag                │
└─────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does shallow routing reload the page component or keep it mounted? Commit to yes or no.
Common Belief:Shallow routing reloads the page component just like normal routing.
Tap to reveal reality
Reality:Shallow routing keeps the current page component mounted and skips data fetching methods.
Why it matters:Believing this causes developers to misuse shallow routing and expect automatic data updates that never happen.
Quick: Can shallow routing be used to navigate between different pages? Commit to yes or no.
Common Belief:Shallow routing works for all URL changes, including different pages.
Tap to reveal reality
Reality:Shallow routing only works within the same page component; navigating to a different page triggers a full reload.
Why it matters:Misusing shallow routing for page changes leads to broken navigation and confusing user experience.
Quick: Does shallow routing automatically update component state to match the new URL? Commit to yes or no.
Common Belief:Shallow routing automatically updates component state to reflect URL changes.
Tap to reveal reality
Reality:Developers must manually listen to route changes and update state; shallow routing only changes the URL and router state.
Why it matters:Assuming automatic updates causes UI and URL to get out of sync, leading to bugs.
Quick: Is shallow routing always faster and better than normal routing? Commit to yes or no.
Common Belief:Shallow routing is always the best choice for navigation.
Tap to reveal reality
Reality:Shallow routing improves speed only for same-page URL changes; for full page changes or data refresh, normal routing is better.
Why it matters:Overusing shallow routing can cause stale data and poor user experience.
Expert Zone
1
Shallow routing does not trigger middleware or server-side redirects, which can cause unexpected behavior if those are relied upon for URL validation.
2
When stacking multiple shallow route changes quickly, the router state can lag behind the URL, requiring debouncing or throttling in complex apps.
3
Shallow routing combined with client-side data fetching libraries allows fine-grained control over when and how data updates, enabling advanced caching and optimistic UI patterns.
When NOT to use
Avoid shallow routing when navigating between different pages or when you need to run server-side data fetching methods. Use normal routing for full page reloads or when middleware and redirects must run. For complex state management, consider using global state libraries instead of relying solely on URL changes.
Production Patterns
In production, shallow routing is often used for pagination, filtering, and sorting in e-commerce or dashboard apps. It is combined with React hooks that listen to router events to fetch data client-side. Developers also use it to preserve scroll position and form inputs during navigation, improving user experience on dynamic pages.
Connections
HTML5 History API
Shallow routing uses the History API to change URLs without page reloads.
Understanding the History API clarifies how shallow routing updates the browser URL smoothly, enabling single-page app behavior.
Client-side State Management
Shallow routing requires manual state updates, linking it closely to client-side state management techniques.
Knowing state management helps handle UI updates after shallow routing, preventing UI and URL mismatches.
User Experience Design
Shallow routing improves perceived app speed and smoothness, key goals in UX design.
Understanding shallow routing helps UX designers and developers collaborate to create seamless navigation flows.
Common Pitfalls
#1Expecting shallow routing to reload data automatically.
Wrong approach:router.push({ pathname: '/products', query: { page: 2 } }, undefined, { shallow: true }) // No code to update data or state after this
Correct approach:router.push({ pathname: '/products', query: { page: 2 } }, undefined, { shallow: true }) useEffect(() => { // Fetch new data based on router.query.page }, [router.query.page])
Root cause:Misunderstanding that shallow routing only changes URL but does not trigger data fetching or state updates.
#2Using shallow routing to navigate between different pages.
Wrong approach:router.push('/about', undefined, { shallow: true })
Correct approach:router.push('/about') // without shallow option for full page navigation
Root cause:Believing shallow routing works for all URL changes, ignoring its limitation to same-page navigation.
#3Not handling route change events after shallow routing.
Wrong approach:router.push({ query: { filter: 'new' } }, undefined, { shallow: true }) // No listener for route changes
Correct approach:router.push({ query: { filter: 'new' } }, undefined, { shallow: true }) useEffect(() => { // Update UI based on router.query.filter }, [router.query.filter])
Root cause:Assuming URL change alone updates UI without explicit state synchronization.
Key Takeaways
Shallow routing updates the browser URL without reloading the page or fetching data again.
It only works within the same page component and requires manual state handling to keep UI in sync.
Using shallow routing improves app speed and user experience by avoiding unnecessary reloads.
Misusing shallow routing for full page navigation or expecting automatic data updates leads to bugs.
Expert use combines shallow routing with client-side data fetching and state management for smooth, dynamic apps.

Practice

(1/5)
1. What does shallow routing in Next.js primarily do?
easy
A. Reloads the entire page to fetch new data
B. Prevents URL changes when navigating
C. Changes the URL without reloading the page or losing component state
D. Forces a full server-side render on every navigation

Solution

  1. Step 1: Understand shallow routing purpose

    Shallow routing updates the URL but keeps the current page component and state intact without a full reload.
  2. Step 2: Compare options with shallow routing behavior

    Only Changes the URL without reloading the page or losing component state describes changing the URL without reloading or losing state, matching shallow routing.
  3. Final Answer:

    Changes the URL without reloading the page or losing component state -> Option C
  4. Quick Check:

    Shallow routing = URL change without reload [OK]
Hint: Shallow routing changes URL but keeps page state [OK]
Common Mistakes:
  • Thinking shallow routing reloads the page
  • Assuming shallow routing blocks URL changes
  • Confusing shallow routing with full page reload
2. Which is the correct way to enable shallow routing using Next.js router's push method?
easy
A. router.push('/page?tab=1', undefined, { shallow: true })
B. router.push('/page?tab=1', { shallow: true })
C. router.push('/page?tab=1', true)
D. router.push('/page?tab=1', { reload: false })

Solution

  1. Step 1: Recall router.push syntax for shallow routing

    The third argument to router.push is an options object where shallow: true enables shallow routing.
  2. Step 2: Match options with correct syntax

    router.push('/page?tab=1', undefined, { shallow: true }) correctly passes { shallow: true } as the third argument; others are incorrect or incomplete.
  3. Final Answer:

    router.push('/page?tab=1', undefined, { shallow: true }) -> Option A
  4. Quick Check:

    Shallow routing option is third argument object [OK]
Hint: Use third argument { shallow: true } in router.push [OK]
Common Mistakes:
  • Passing shallow option as second argument
  • Using boolean instead of options object
  • Confusing reload option with shallow
3. Given this code snippet in a Next.js page component:
const router = useRouter();

useEffect(() => {
  console.log('Query changed:', router.query.tab);
}, [router.query.tab]);

const changeTab = () => {
  router.push('/dashboard?tab=2', undefined, { shallow: true });
};

changeTab();

What will be logged to the console after changeTab() is called?
medium
A. Query changed: 2
B. Query changed: undefined
C. Nothing is logged because shallow routing blocks query updates
D. An error occurs because shallow routing cannot update query

Solution

  1. Step 1: Understand effect dependency on router.query.tab

    The effect runs when router.query.tab changes, logging its value.
  2. Step 2: Analyze shallow routing effect on query

    Shallow routing updates the URL and query parameters without full reload, so router.query.tab updates to '2'.
  3. Final Answer:

    Query changed: 2 -> Option A
  4. Quick Check:

    Shallow routing updates query and triggers effects [OK]
Hint: Shallow routing updates query, triggers effects [OK]
Common Mistakes:
  • Assuming shallow routing blocks query updates
  • Expecting no console output
  • Thinking shallow routing causes errors
4. Consider this Next.js code snippet:
const router = useRouter();

const handleClick = () => {
  router.push('/profile?section=info', undefined, { shallow: true });
  router.push('/profile?section=details');
};

handleClick();

What is the problem with this code regarding shallow routing?
medium
A. No problem; shallow routing applies to both pushes automatically
B. Shallow routing is ignored because it must be the first push
C. Both pushes cause full reloads because shallow routing is not supported
D. The second push overrides shallow routing, causing a full reload

Solution

  1. Step 1: Examine the two router.push calls

    The first call uses shallow routing, the second does not and triggers a full reload.
  2. Step 2: Understand effect of second push on routing

    The second push overrides the first and causes a full page reload, negating shallow routing.
  3. Final Answer:

    The second push overrides shallow routing, causing a full reload -> Option D
  4. Quick Check:

    Non-shallow push cancels shallow routing [OK]
Hint: Later push without shallow cancels shallow routing [OK]
Common Mistakes:
  • Assuming shallow routing applies to all pushes automatically
  • Thinking shallow routing must be first push only
  • Ignoring that non-shallow push triggers reload
5. You want to implement tab navigation in a Next.js page using shallow routing to update the URL query without losing component state. Which approach correctly achieves this?
hard
A. Use router.replace without shallow option to update URL and reset state
B. Use router.push with { shallow: true } when changing tabs and listen to router.query to update UI
C. Reload the page on every tab click to fetch fresh data
D. Manually manipulate window.location to change URL without Next.js router

Solution

  1. Step 1: Identify shallow routing usage for tab navigation

    Using router.push with { shallow: true } updates URL query without full reload, preserving component state.
  2. Step 2: Confirm UI updates from router.query changes

    Listening to router.query allows UI to react to tab changes smoothly without losing state.
  3. Final Answer:

    Use router.push with { shallow: true } and listen to router.query -> Option B
  4. Quick Check:

    Shallow routing + query listening = smooth tab navigation [OK]
Hint: Use router.push with shallow and watch router.query [OK]
Common Mistakes:
  • Reloading page loses component state
  • Using router.replace without shallow resets state
  • Manipulating window.location breaks SPA behavior
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard