iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🍈

To what extent can next/navigation be used in Next.js Pages Router?

に公開

When porting Next.js from Pages Router to App Router, it becomes necessary to replace useRouter from next/router.
If you have written logic such as fetching queries or parameters within components, you might occasionally encounter minor issues with shared components.

Regarding this replacement, instead of migrating to App Router all at once:

  1. Replace useRouter from next/router with useParams or useSearchParams from next/navigation in components used on the Pages Router.
  2. Once the replacement is finished, port them to App Router.

I thought that if this procedure could be followed, the migration could be performed relatively safely and would assist with the migration process.

Can next/navigation hooks be used in Pages Router?

While there is no explicit mention of such a migration path, I found the following description in the useParams documentation:

If used in Pages Router, useParams will return null on the initial render and updates with properties following the rules above once the router is ready.

Based on this, it seems reasonable to assume that its use in the Pages Router is also intended.

Also, looking at issues like the ones below, they are trying to maintain as much compatibility as possible:

Therefore, it seems basically fine to replace them beforehand.

How much of a difference is there?

From here, I will compare the differences between them.

In this case, we will compare based on a scenario: what values are obtained when accessing a page like

sample/a/b/c?d=e

for a route such as

sample/[p]/[[...q]].tsx?

import { useRouter } from 'next/router'

const router = useRouter()

// Parameter-related
console.log(router.query) 
// => {"d":"e","p":"a","q":["b","c"]} 

import { useParams,  useSearchParams } from 'next/navigation'

const params = useParams()
const searchParams = useSearchParams()

// Parameter-related
console.log(JSON.stringify(params))
// => {"p":"a","q":["b","c"]}
console.log(JSON.stringify(Object.fromEntries(searchParams ?? [])))
// => {"d":"e"}

  • While useRouter's query allowed for retrieving both dynamic parameters and query parameters together, next/navigation requires you to retrieve useParams and useSearchParams separately.
    • Since useSearchParams is retrieved in the form of URLSearchParams, the example above converts it to an object using Object.fromEntries for display purposes.
    • For more specific details about the return value of useSearchParams, you should refer to the documentation.
import { useRouter } from 'next/router'

const router = useRouter()

console.log(router.pathname) 
// => /sample/[p]/[[...q]] 
console.log(router.asPath) 
// => /sample/a/b/c?d=e
import { usePathname } from 'next/navigation'

const pathname = usePathname()

console.log(pathname)
// => /sample/a/b/c

Regarding paths, there doesn't seem to be a direct equivalent, and it was difficult to retrieve the pre-transformed path like /sample/[p]/[[...q]]. Since this was occasionally used for conditional display in navigation-related logic, some alternative approach might need to be devised in those cases.

Navigation-related functions such as push and back are mostly available in the useRouter hook of the same name within next/navigation, so they can be used.

However, the documentation doesn't mention their use in the Pages Router, so some caution may be required.

Other missing features

The following features did not seem to exist:

  • Status properties such as isReady and isPreview
  • Locale-related properties

Summary

  • For simple parameter fetching, it is practically possible to use next/navigation proactively on the Pages Router.
  • Since specific behaviors do not match exactly, you should be cautious when applying this method to complex or special logic.
GitHubで編集を提案

Discussion