From 496e38c84422dba8b34a46e5fe5ce8b637a1fa05 Mon Sep 17 00:00:00 2001 From: Delba de Oliveira <32464864+delbaoliveira@users.noreply.github.com> Date: Thu, 11 Jan 2024 02:59:09 +0000 Subject: [PATCH] Docs: Document `windowHistorySupport` flag, and add `pushState`/`replaceState` examples (#60374) --- .../01-routing/03-linking-and-navigating.mdx | 113 +++++++++++++++++- .../windowHistorySupport.mdx | 20 ++++ 2 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 docs/02-app/02-api-reference/05-next-config-js/windowHistorySupport.mdx diff --git a/docs/02-app/01-building-your-application/01-routing/03-linking-and-navigating.mdx b/docs/02-app/01-building-your-application/01-routing/03-linking-and-navigating.mdx index 2e1b9e0120..747a0e75b8 100644 --- a/docs/02-app/01-building-your-application/01-routing/03-linking-and-navigating.mdx +++ b/docs/02-app/01-building-your-application/01-routing/03-linking-and-navigating.mdx @@ -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 [`` 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 ``, `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. ## `` Component -`` is a built-in component that extends the HTML `` tag to provide [prefetching](#2-prefetching) and client-side navigation between routes. It is the primary way to navigate between routes in Next.js. +`` is a built-in component that extends the HTML `` 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 `` 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 ( + <> + + + + ) +} +``` + +```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 ( + <> + + + + ) +} +``` + +### `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 ( + <> + + + + ) +} +``` + +```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 ( + <> + + + + ) +} +``` + ## 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. diff --git a/docs/02-app/02-api-reference/05-next-config-js/windowHistorySupport.mdx b/docs/02-app/02-api-reference/05-next-config-js/windowHistorySupport.mdx new file mode 100644 index 0000000000..413c05d587 --- /dev/null +++ b/docs/02-app/02-api-reference/05-next-config-js/windowHistorySupport.mdx @@ -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.