Skip to content

Commit

Permalink
Docs: Document windowHistorySupport flag, and add pushState/`repl…
Browse files Browse the repository at this point in the history
…aceState` examples (#60374)
  • Loading branch information
delbaoliveira authored Jan 11, 2024
1 parent ca5bc98 commit 496e38c
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ related:
- app/building-your-application/configuring/typescript
---

There are two ways to navigate between routes in Next.js:
There are three ways to navigate between routes in Next.js:

- Using the [`<Link>` Component](#link-component)
- Using the [`useRouter` Hook](#userouter-hook)
- Using the native [History API](#using-the-native-history-api)

This page will go through how to use `<Link>`, `useRouter()`, and dive deeper into how navigation works.
This page will go through how to use each of these options, and dive deeper into how navigation works.

## `<Link>` Component

`<Link>` is a built-in component that extends the HTML `<a>` tag to provide [prefetching](#2-prefetching) and client-side navigation between routes. It is the primary way to navigate between routes in Next.js.
`<Link>` is a built-in component that extends the HTML `<a>` tag to provide [prefetching](#2-prefetching) and client-side navigation between routes. It is the primary and recommended way to navigate between routes in Next.js.

You can use it by importing it from `next/link`, and passing a `href` prop to the component:

Expand Down Expand Up @@ -183,6 +184,112 @@ For a full list of `useRouter` methods, see the [API reference](/docs/app/api-re

> **Recommendation:** Use the `<Link>` component to navigate between routes unless you have a specific requirement for using `useRouter`.
## Using the native History API

Next.js allows you to use the native [`window.history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) and [`window.history.replaceState`](https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState) methods to update the browser's history stack without reloading the page.

This behavior is enabled with the Next.js [`windowHistorySupport`](/docs/app/api-reference/next-config-js/windowHistorySupport) config option. When the flag is set to `true`, `pushState` and `replaceState` calls integrate into the Next.js Router, allowing you to sync with [`usePathname`](/docs/app/api-reference/functions/use-pathname) and [`useSearchParams`](/docs/app/api-reference/functions/use-search-params).

### `window.history.pushState`

Use it to add a new entry to the browser's history stack. The user can navigate back to the previous state. For example, to sort a list of products:

```tsx fileName="app/ui/sort-products.tsx" switcher
'use client'

import { useSearchParams } from 'next/navigation'

export default function SortProducts() {
const searchParams = useSearchParams()

function updateSorting(sortOrder: string) {
const params = new URLSearchParams(searchParams.toString())
params.set('sort', sortOrder)
window.history.pushState(null, '', `?${params.toString()}`)
}

return (
<>
<button onClick={() => updateSorting('asc')}>Sort Ascending</button>
<button onClick={() => updateSorting('desc')}>Sort Descending</button>
</>
)
}
```

```jsx fileName="app/ui/sort-products.js" switcher
'use client'

import { useSearchParams } from 'next/navigation'

export default function SortProducts() {
const searchParams = useSearchParams()

function updateSorting(sortOrder) {
const params = new URLSearchParams(searchParams.toString())
params.set('sort', sortOrder)
window.history.pushState(null, '', `?${params.toString()}`)
}

return (
<>
<button onClick={() => updateSorting('asc')}>Sort Ascending</button>
<button onClick={() => updateSorting('desc')}>Sort Descending</button>
</>
)
}
```

### `window.history.replaceState`

Use it to replace the current entry on the browser's history stack. The user is not able to navigate back to the previous state. For example, to switch the application's locale:

```tsx fileName="app/ui/locale-switcher.tsx" switcher
'use client'

import { usePathname } from 'next/navigation'

export function LocaleSwitcher() {
const pathname = usePathname()

function switchLocale(locale: string) {
// e.g. '/en/about' or '/fr/contact'
const newPath = `/${locale}${pathname}`
window.history.replaceState(null, '', newPath)
}

return (
<>
<button onClick={() => switchLocale('en')}>English</button>
<button onClick={() => switchLocale('fr')}>French</button>
</>
)
}
```

```jsx fileName="app/ui/locale-switcher.js" switcher
'use client'

import { usePathname } from 'next/navigation'

export function LocaleSwitcher() {
const pathname = usePathname()

function switchLocale(locale) {
// e.g. '/en/about' or '/fr/contact'
const newPath = `/${locale}${pathname}`
window.history.replaceState(null, '', newPath)
}

return (
<>
<button onClick={() => switchLocale('en')}>English</button>
<button onClick={() => switchLocale('fr')}>French</button>
</>
)
}
```

## How Routing and Navigation Works

The App Router uses a hybrid approach for routing and navigation. On the server, your application code is automatically [code-split](#1-code-splitting) by route segments. And on the client, Next.js [prefetches](#2-prefetching) and [caches](#3-caching) the route segments. This means, when a user navigates to a new route, the browser doesn't reload the page, and only the route segments that change re-render - improving the navigation experience and performance.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: webVitalsAttribution
description: Learn how to use the webVitalsAttribution option to pinpoint the source of Web Vitals issues.
---

`windowHistorySupport` is an experimental flag that allows you manually call [`window.history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) and [`window.history.replaceState`](https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState).

When the flag is enabled, `pushState` and `replaceState` calls are integrated into the Next.js Router, allowing you to sync with [`usePathname`](/docs/app/api-reference/functions/use-pathname) and [`useSearchParams`](/docs/app/api-reference/functions/use-search-params).

To use it, set `windowHistorySupport` to `true` in your `next.config.js` file:

```js fileName="next.config.js"
module.exports = {
experimental: {
windowHistorySupport: true,
},
}
```

See the [Linking and Navigation](/docs/app/building-your-application/routing/linking-and-navigating#using-the-native-history-api) documentation for examples.

0 comments on commit 496e38c

Please sign in to comment.