📖 Scenario: You are building a simple Next.js app that shows a list of products. You want to change the URL query parameters when a user selects a product category, but you want to keep the page from fully reloading or fetching new data from the server.
🎯 Goal: Build a Next.js page that uses shallow routing to update the URL query string without triggering a full page reload or data fetch.
📋 What You'll Learn
Create a Next.js page component named ProductsPage with a list of product categories.
Add a state variable called category to track the selected category.
Use Next.js useRouter hook to update the URL query parameter category with shallow routing.
Render the selected category on the page and update the URL without full reload.
💡 Why This Matters
🌍 Real World
Shallow routing is useful in web apps where you want to update the URL to reflect UI state changes without reloading the page or fetching new data. For example, filtering products or paginating content.
💼 Career
Understanding shallow routing helps you build faster, smoother Next.js applications that improve user experience by avoiding unnecessary page reloads.
Progress0 / 4 steps
1
Setup initial product categories and state
Create a functional component called ProductsPage. Inside it, create a constant array named categories with these exact strings: 'all', 'books', 'electronics'. Also, create a state variable called category initialized to 'all' using useState.
NextJS
Hint
Use useState to create category and setCategory. Define categories as an array with the exact strings.
2
Add Next.js router and handle category change
Import useRouter from next/router. Inside ProductsPage, create a constant router by calling useRouter(). Then, write a function called handleCategoryChange that takes a parameter newCategory and calls setCategory(newCategory).
NextJS
Hint
Import useRouter and call it inside the component. Define handleCategoryChange to update the state.
3
Use shallow routing to update URL query
Inside the handleCategoryChange function, after setCategory(newCategory), call router.push to update the URL with the query parameter category=newCategory. Use the current pathname from router.pathname. Pass an options object with shallow: true to enable shallow routing.
NextJS
Hint
Use router.push with an object for pathname and query. Add { shallow: true } as the third argument.
4
Render category buttons and display selected category
In the return statement of ProductsPage, render a div containing a button for each category in categories. Each button should have an onClick handler that calls handleCategoryChange with the category string. Below the buttons, render a p element that displays the text Selected category: {category}.
NextJS
Hint
Use categories.map to create buttons. Each button calls handleCategoryChange with the category string. Show the selected category in a paragraph.
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
Step 1: Understand shallow routing purpose
Shallow routing updates the URL but keeps the current page component and state intact without a full reload.
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.
Final Answer:
Changes the URL without reloading the page or losing component state -> Option C
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
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.
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.
Final Answer:
router.push('/page?tab=1', undefined, { shallow: true }) -> Option A
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:
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
Step 1: Examine the two router.push calls
The first call uses shallow routing, the second does not and triggers a full reload.
Step 2: Understand effect of second push on routing
The second push overrides the first and causes a full page reload, negating shallow routing.
Final Answer:
The second push overrides shallow routing, causing a full reload -> Option D
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
Step 1: Identify shallow routing usage for tab navigation
Using router.push with { shallow: true } updates URL query without full reload, preserving component state.
Step 2: Confirm UI updates from router.query changes
Listening to router.query allows UI to react to tab changes smoothly without losing state.
Final Answer:
Use router.push with { shallow: true } and listen to router.query -> Option B