Skip to content

Commit

Permalink
docs mention next/compat/router (#70425)
Browse files Browse the repository at this point in the history
Lands #54317 as we can't update
the history cleanly on that PR anymore

Closes: #54317

Co-authored-by: Andrés Martínez <78830288+andresmarpz@users.noreply.github.com>
  • Loading branch information
ijjk and andresmarpz committed Sep 24, 2024
1 parent fb1659a commit aecc50e
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,11 @@ In addition, the new `useRouter` hook has the following changes:
[View the `useRouter()` API reference](/docs/app/api-reference/functions/use-router).
#### Sharing components between `pages` and `app`
To keep components compatible between the `pages` and `app` routers, refer to the [`useRouter` hook from `next/compat/router`](/docs/pages/api-reference/functions/use-router#the-nextcompatrouter-export).
This is the `useRouter` hook from the `pages` directory, but intented to be used while sharing components between routers. Once you are ready to use it only on the `app` router, update to the new [`useRouter` from `next/navigation`](/docs/app/api-reference/functions/use-router).
### Step 6: Migrating Data Fetching Methods
The `pages` directory uses `getServerSideProps` and `getStaticProps` to fetch data for pages. Inside the `app` directory, these previous data fetching functions are replaced with a [simpler API](/docs/app/building-your-application/data-fetching) built on top of `fetch()` and `async` React Server Components.
Expand Down
72 changes: 72 additions & 0 deletions docs/03-pages/02-api-reference/03-functions/use-router.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,78 @@ export default function MyApp({ Component, pageProps }) {
}
```

## The `next/compat/router` export

This is the same `useRouter` hook, but can be used in both `app` and `pages` directories.

It differs from `next/router` in that it does not throw an error when the pages router is not mounted, and instead has a return type of `NextRouter | null`.
This allows developers to convert components to support running in both `app` and `pages` as they transition to the `app` router.

A component that previously looked like this:

```jsx
import { useRouter } from 'next/router'
const MyComponent = () => {
const { isReady, query } = useRouter()
// ...
}
```

Will error when converted over to `next/compat/router`, as `null` can not be destructured. Instead, developers will be able to take advantage of new hooks:

```jsx
import { useEffect } from 'react'
import { useRouter } from 'next/compat/router'
import { useSearchParams } from 'next/navigation'
const MyComponent = () => {
const router = useRouter() // may be null or a NextRouter instance
const searchParams = useSearchParams()
useEffect(() => {
if (router && !router.isReady) {
return
}
// In `app/`, searchParams will be ready immediately with the values, in
// `pages/` it will be available after the router is ready.
const search = searchParams.get('search')
// ...
}, [router, searchParams])
// ...
}
```

This component will now work in both `pages` and `app` directories. When the component is no longer used in `pages`, you can remove the references to the compat router:

```jsx
import { useSearchParams } from 'next/navigation'
const MyComponent = () => {
const searchParams = useSearchParams()
// As this component is only used in `app/`, the compat router can be removed.
const search = searchParams.get('search')
// ...
}
```

### Using `useRouter` outside of Next.js context in pages

Another specific use case is when rendering components outside of a Next.js application context, such as inside `getServerSideProps` on the `pages` directory. In this case, the compat router can be used to avoid errors:

```jsx
import { renderToString } from 'react-dom/server'
import { useRouter } from 'next/compat/router'
const MyComponent = () => {
const router = useRouter() // may be null or a NextRouter instance
// ...
}
export async function getServerSideProps() {
const renderedComponent = renderToString(<MyComponent />)
return {
props: {
renderedComponent,
},
}
}
```

## Potential ESLint errors

Certain methods accessible on the `router` object return a Promise. If you have the ESLint rule, [no-floating-promises](https://typescript-eslint.io/rules/no-floating-promises) enabled, consider disabling it either globally, or for the affected line.
Expand Down
2 changes: 2 additions & 0 deletions errors/next-router-not-mounted.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ If used in a test, mock out the router by mocking the `next/router`'s `useRouter

If used in the `app` directory, migrate to the new hooks imported from `next/navigation`.

If used in the `pages` directory, try to update the export to [`next/compat/router`](/docs/pages/api-reference/functions/use-router#the-nextcompatrouter-export). This is the same `useRouter` hook but does not throw this error, intended to be used while migrating from `pages` to `app`.

## Useful Links

- [next-router-mock](https://www.npmjs.com/package/next-router-mock)
Expand Down

0 comments on commit aecc50e

Please sign in to comment.