mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
### What? Polishes the dev-overlay UX for the client-hook prerender error after Josh's framework fix landed in [#94494](https://github.com/vercel/next.js/pull/94494). The overlay now names the hook in the headline and shows per-hook fix cards. ### Why? Different hooks need different fixes. `useSearchParams` always suspends, but `generateStaticParams` doesn't apply to it. `useParams` is the only hook GSP resolves at build time. `usePathname` and `useSelectedLayoutSegment(s)` need a Suspense boundary or the `[block]` export. ### How? - Headline now reads "Next.js encountered URL data `useX()` in a Client Component outside of `<Suspense>`", matching the body factory wording. - Per-hook card sets in `instant-guidance-data.ts`: `useSearchParams` → Stream + Block; `useParams` → Stream + GSP + Block; `usePathname` / `useSelectedLayoutSegment(s)` → Stream + Block. - Build-time message in `ClientHookDynamicError` / `ParamClientHookDynamicError` matches the overlay card set. - Companion docs page: [vercel/front#72622](https://github.com/vercel/front/pull/72622). ### Verification Demo scenarios on the [error-messages-overhaul test app](https://error-messages-overhaul-ibsl.labs.vercel.dev/): [88-client-use-pathname](https://error-messages-overhaul-ibsl.labs.vercel.dev/scenario/88-client-use-pathname), [89-client-use-search-params](https://error-messages-overhaul-ibsl.labs.vercel.dev/scenario/89-client-use-search-params), [90-client-use-params](https://error-messages-overhaul-ibsl.labs.vercel.dev/scenario/90-client-use-params), [91-client-use-selected-layout-segment](https://error-messages-overhaul-ibsl.labs.vercel.dev/scenario/91-client-use-selected-layout-segment), [92-client-use-selected-layout-segments](https://error-messages-overhaul-ibsl.labs.vercel.dev/scenario/92-client-use-selected-layout-segments). <!-- NEXT_JS_LLM_PR --> --------- Co-authored-by: Josh Story <[email protected]>
168 lines
7.2 KiB
Plaintext
168 lines
7.2 KiB
Plaintext
---
|
|
title: usePathname
|
|
description: API Reference for the usePathname hook.
|
|
---
|
|
|
|
`usePathname` is a **Client Component** hook that lets you read the current URL's **pathname**.
|
|
|
|
```tsx filename="app/example-client-component.tsx" switcher
|
|
'use client'
|
|
|
|
import { usePathname } from 'next/navigation'
|
|
|
|
export default function ExampleClientComponent() {
|
|
const pathname = usePathname()
|
|
return <p>Current pathname: {pathname}</p>
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/example-client-component.js" switcher
|
|
'use client'
|
|
|
|
import { usePathname } from 'next/navigation'
|
|
|
|
export default function ExampleClientComponent() {
|
|
const pathname = usePathname()
|
|
return <p>Current pathname: {pathname}</p>
|
|
}
|
|
```
|
|
|
|
`usePathname` intentionally requires using a [Client Component](/docs/app/getting-started/server-and-client-components). It's important to note Client Components are not a de-optimization. They are an integral part of the [Server Components](/docs/app/getting-started/server-and-client-components) architecture.
|
|
|
|
For example, a Client Component with `usePathname` will be rendered into HTML on the initial page load. When navigating to a new route, this component does not need to be re-fetched. Instead, the component is downloaded once (in the client JavaScript bundle), and re-renders based on the current state.
|
|
|
|
> **Good to know**:
|
|
>
|
|
> - Reading the current URL from a [Server Component](/docs/app/getting-started/server-and-client-components) is not supported. This design is intentional to support layout state being preserved across page navigations.
|
|
> - If your page is being statically prerendered and your app has [rewrites](/docs/app/api-reference/config/next-config-js/rewrites) in `next.config` or a [Proxy](/docs/app/api-reference/file-conventions/proxy) file, reading the pathname with `usePathname()` can result in hydration mismatch errors, because the initial value comes from the server and may not match the actual browser pathname after routing. See our [example](#avoid-hydration-mismatch-with-rewrites) for a way to mitigate this issue.
|
|
|
|
<details>
|
|
|
|
<summary>Compatibility with Pages Router</summary>
|
|
|
|
If you have components that use `usePathname` and they are imported into routes within the Pages Router, be aware that `usePathname` may return `null` if the router is not yet initialized. This can occur in cases such as [fallback routes](/docs/pages/api-reference/functions/get-static-paths#fallback-true) or during [Automatic Static Optimization](/docs/pages/building-your-application/rendering/automatic-static-optimization) in the Pages Router.
|
|
|
|
To enhance compatibility between routing systems, if your project contains both an `app` and a `pages` directory, Next.js will automatically adjust the return type of `usePathname`.
|
|
|
|
</details>
|
|
|
|
## Parameters
|
|
|
|
```tsx
|
|
const pathname = usePathname()
|
|
```
|
|
|
|
`usePathname` does not take any parameters.
|
|
|
|
## Returns
|
|
|
|
`usePathname` returns a string of the current URL's pathname. For example:
|
|
|
|
| URL | Returned value |
|
|
| ------------------- | --------------------- |
|
|
| `/` | `'/'` |
|
|
| `/dashboard` | `'/dashboard'` |
|
|
| `/dashboard?v=2` | `'/dashboard'` |
|
|
| `/blog/hello-world` | `'/blog/hello-world'` |
|
|
|
|
## Behavior
|
|
|
|
### Cache Components
|
|
|
|
When [`cacheComponents`](/docs/app/api-reference/config/next-config-js/cacheComponents) is enabled, `usePathname` may require a [`Suspense`](https://react.dev/reference/react/Suspense) boundary. This depends on whether the pathname can be resolved during prerendering.
|
|
|
|
- **Static routes and routes with [`generateStaticParams`](/docs/app/api-reference/functions/generate-static-params)**: every route segment, including dynamic params, is known at build time. The pathname can be resolved during prerendering, so `usePathname` resolves on the server and no `Suspense` boundary is required.
|
|
- **Routes with dynamic params not covered by `generateStaticParams`**: the param is a [fallback param](/docs/app/api-reference/functions/generate-static-params#all-paths-at-build-time) that is not known until request time. The pathname cannot be resolved during prerendering, so `usePathname` suspends. Wrap the component (or a parent) in a `Suspense` boundary so its fallback can be rendered during prerendering; otherwise, the build fails.
|
|
|
|
This applies even when the component that calls `usePathname` is itself static. For example, a sidebar with active links rendered in a layout suspends on any page below it that has an unknown dynamic param. To keep the rest of the layout prerendered, wrap the component that calls `usePathname` (or a parent) in a `Suspense` boundary with a fallback.
|
|
|
|
See [Next.js encountered URL data in a Client Component outside of Suspense](/docs/messages/blocking-prerender-client-hook) for full fix options and trade-offs.
|
|
|
|
## Examples
|
|
|
|
### Do something in response to a route change
|
|
|
|
```tsx filename="app/example-client-component.tsx" switcher
|
|
'use client'
|
|
|
|
import { useEffect } from 'react'
|
|
import { usePathname, useSearchParams } from 'next/navigation'
|
|
|
|
function ExampleClientComponent() {
|
|
const pathname = usePathname()
|
|
const searchParams = useSearchParams()
|
|
useEffect(() => {
|
|
// Do something here...
|
|
}, [pathname, searchParams])
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/example-client-component.js" switcher
|
|
'use client'
|
|
|
|
import { useEffect } from 'react'
|
|
import { usePathname, useSearchParams } from 'next/navigation'
|
|
|
|
function ExampleClientComponent() {
|
|
const pathname = usePathname()
|
|
const searchParams = useSearchParams()
|
|
useEffect(() => {
|
|
// Do something here...
|
|
}, [pathname, searchParams])
|
|
}
|
|
```
|
|
|
|
### Avoid hydration mismatch with rewrites
|
|
|
|
When a page is prerendered, the HTML is generated for the source pathname. If the page is then reached through a rewrite using `next.config` or `Proxy`, the browser URL may differ, and `usePathname()` will read the rewritten pathname on the client.
|
|
|
|
To avoid hydration mismatches, design the UI so that only a small, isolated part depends on the client pathname. Render a stable fallback on the server and update that part after mount. The deferred read shows a brief moment of the fallback before the real pathname appears; see [Preventing flash before hydration](/docs/app/guides/preventing-flash-before-hydration) for techniques that eliminate the visible flicker.
|
|
|
|
```tsx filename="app/example-client-component.tsx" switcher
|
|
'use client'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
import { usePathname } from 'next/navigation'
|
|
|
|
export default function PathnameBadge() {
|
|
const pathname = usePathname()
|
|
const [clientPathname, setClientPathname] = useState('')
|
|
|
|
useEffect(() => {
|
|
setClientPathname(pathname)
|
|
}, [pathname])
|
|
|
|
return (
|
|
<p>
|
|
Current pathname: <span>{clientPathname}</span>
|
|
</p>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/example-client-component.js" switcher
|
|
'use client'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
import { usePathname } from 'next/navigation'
|
|
|
|
export default function PathnameBadge() {
|
|
const pathname = usePathname()
|
|
const [clientPathname, setClientPathname] = useState('')
|
|
|
|
useEffect(() => {
|
|
setClientPathname(pathname)
|
|
}, [pathname])
|
|
|
|
return (
|
|
<p>
|
|
Current pathname: <span>{clientPathname}</span>
|
|
</p>
|
|
)
|
|
}
|
|
```
|
|
|
|
| Version | Changes |
|
|
| --------- | ------------------------- |
|
|
| `v13.0.0` | `usePathname` introduced. |
|