Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Opting out of scrolling with next/link and useRouter. #53804

Merged
merged 2 commits into from Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -95,7 +95,7 @@ export function Navigation({ navLinks }) {

#### Scrolling to an `id`

The default behavior of `<Link>` is to scroll to the top of a new route or to maintain the scroll position for backwards and forwards navigation.
The default behavior of the Next.js App Router is to scroll to the top of a new route or to maintain the scroll position for backwards and forwards navigation.

If you'd like to scroll to a specific `id` on navigation, you can append your URL with a `#` hash link or just pass a hash link to the `href` prop. This is possible since `<Link>` renders to an `<a>` element.

Expand All @@ -106,6 +106,24 @@ If you'd like to scroll to a specific `id` on navigation, you can append your UR
<a href="/dashboard#settings">Settings</a>
```

#### Disabling scroll restoration

The default behavior of the Next.js App Router is to scroll to the top of a new route or to maintain the scroll position for backwards and forwards navigation. If you'd like to disable this behavior, you can pass `scroll={false}` to the `<Link>` component, or `scroll: false` to `router.push()` or `router.replace()`.

```jsx
// next/link
<Link href="/dashboard" scroll={false}>
Dashboard
</Link>
```

```jsx
// useRouter
import { useRouter } from 'next/navigation'

router.push('/dashboard', { scroll: false })
```

## `useRouter()` Hook

The `useRouter` hook allows you to programmatically change routes.
Expand Down
29 changes: 29 additions & 0 deletions docs/02-app/02-api-reference/01-components/link.mdx
Expand Up @@ -77,6 +77,7 @@ Here's a summary of the props available for the Link Component:
| ------------------------ | ------------------- | ---------------- | -------- |
| [`href`](#href-required) | `href="/dashboard"` | String or Object | Yes |
| [`replace`](#replace) | `replace={false}` | Boolean | - |
| [`scroll`](#scroll) | `scroll={false}` | Boolean | - |
| [`prefetch`](#prefetch) | `prefetch={false}` | Boolean | - |

> **Good to know**: `<a>` tag attributes such as `className` or `target="_blank"` can be added to `<Link>` as props and will be passed to the underlying `<a>` element.
Expand Down Expand Up @@ -131,6 +132,34 @@ export default function Page() {
}
```

### `scroll`

**Defaults to `true`.** The default behavior of `<Link>` is to scroll to the top of a new route or to maintain the scroll position for backwards and forwards navigation. When `false`, `next/link` will _not_ scroll to the top of the page after a navigation.

```tsx filename="app/page.tsx" switcher
import Link from 'next/link'

export default function Page() {
return (
<Link href="/dashboard" scroll={false}>
Dashboard
</Link>
)
}
```

```jsx filename="app/page.js" switcher
import Link from 'next/link'

export default function Page() {
return (
<Link href="/dashboard" scroll={false}>
Dashboard
</Link>
)
}
```

### `prefetch`

**Defaults to `true`.** When `true`, `next/link` will prefetch the page (denoted by the `href`) in the background. This is useful for improving the performance of client-side navigations. Any `<Link />` in the viewport (initially or through scroll) will be preloaded.
Expand Down
66 changes: 55 additions & 11 deletions docs/02-app/02-api-reference/04-functions/use-router.mdx
Expand Up @@ -41,8 +41,8 @@ export default function Page() {

## `useRouter()`

- `router.push(href: string)`: Perform a client-side navigation to the provided route. Adds a new entry into the [browser’s history](https://developer.mozilla.org/en-US/docs/Web/API/History_API) stack.
- `router.replace(href: string)`: Perform a client-side navigation to the provided route without adding a new entry into the [browser’s history stack](https://developer.mozilla.org/en-US/docs/Web/API/History_API).
- `router.push(href: string, { scroll: boolean })`: Perform a client-side navigation to the provided route. Adds a new entry into the [browser’s history](https://developer.mozilla.org/en-US/docs/Web/API/History_API) stack.
- `router.replace(href: string, { scroll: boolean })`: Perform a client-side navigation to the provided route without adding a new entry into the [browser’s history stack](https://developer.mozilla.org/en-US/docs/Web/API/History_API).
- `router.refresh()`: Refresh the current route. Making a new request to the server, re-fetching data requests, and re-rendering Server Components. The client will merge the updated React Server Component payload without losing unaffected client-side React (e.g. `useState`) or browser state (e.g. scroll position).
- `router.prefetch(href: string)`: [Prefetch](/docs/app/building-your-application/routing/linking-and-navigating#1-prefetching) the provided route for faster client-side transitions.
- `router.back()`: Navigate back to the previous route in the browser’s history stack.
Expand All @@ -53,18 +53,18 @@ export default function Page() {
> - The `<Link>` component automatically prefetch routes as they become visible in the viewport.
> - `refresh()` could re-produce the same result if fetch requests are cached. Other dynamic functions like `cookies` and `headers` could also change the response.

> **Migrating from the `pages` directory:**
>
> - The new `useRouter` hook should be imported from `next/navigation` and not `next/router`
> - The `pathname` string has been removed and is replaced by [`usePathname()`](/docs/app/api-reference/functions/use-pathname)
> - The `query` object has been removed and is replaced by [`useSearchParams()`](/docs/app/api-reference/functions/use-search-params)
> - `router.events` is not currently supported. [See below.](#router-events)
>
> [View the full migration guide](/docs/app/building-your-application/upgrading/app-router-migration).
### Migrating from `next/router`

- The `useRouter` hook should be imported from `next/navigation` and not `next/router` when using the App Router
- The `pathname` string has been removed and is replaced by [`usePathname()`](/docs/app/api-reference/functions/use-pathname)
- The `query` object has been removed and is replaced by [`useSearchParams()`](/docs/app/api-reference/functions/use-search-params)
- `router.events` has been replaced. [See below.](#router-events)

[View the full migration guide](/docs/app/building-your-application/upgrading/app-router-migration).

## Examples

### Router Events
### Router events

You can listen for page changes by composing other Client Component hooks like `usePathname` and `useSearchParams`.

Expand Down Expand Up @@ -112,6 +112,50 @@ export default function Layout({ children }) {

> **Good to know**: `<NavigationEvents>` is wrapped in a [`Suspense` boundary](/docs/app/building-your-application/routing/loading-ui-and-streaming#example) because[`useSearchParams()`](/docs/app/api-reference/functions/use-search-params) causes client-side rendering up to the closest `Suspense` boundary during [static rendering](/docs/app/building-your-application/rendering/static-and-dynamic#static-rendering-default). [Learn more](/docs/app/api-reference/functions/use-search-params#behavior).

### Disabling scroll restoration

By default, Next.js will scroll to the top of the page when navigating to a new route. You can disable this behavior by passing `scroll: false` to `router.push()` or `router.replace()`.

```tsx filename="app/example-client-component.tsx" switcher
'use client'

import { useRouter } from 'next/navigation'

export default function Page() {
const router = useRouter()

return (
<button
type="button"
onClick={() => router.push('/dashboard', { scroll: false })}
>
Dashboard
</button>
)
}
```

```jsx filename="app/example-client-component.jsx" switcher
'use client'

import { useRouter } from 'next/navigation'

export default function Page() {
const router = useRouter()

return (
<button
type="button"
onClick={() => router.push('/dashboard', { scroll: false })}
>
Dashboard
</button>
)
}
```

## Version History

| Version | Changes |
| --------- | ---------------------------------------------- |
| `v13.0.0` | `useRouter` from `next/navigation` introduced. |