Docs: Document windowHistorySupport flag, and add pushState/replaceState examples (#60374)

This commit is contained in:
Delba de Oliveira 2024-01-11 02:59:09 +00:00 committed by GitHub
parent ca5bc989d1
commit 496e38c844
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 130 additions and 3 deletions

View file

@ -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:
@ -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.

View file

@ -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.