docs/01-app/03-api-reference/04-functions/use-selected-layout-segment.mdx
useSelectedLayoutSegment is a Client Component hook that lets you read the active route segment one level below the Layout it is called from.
It is useful for navigation UI, such as tabs inside a parent layout that change style depending on the active child segment.
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
export default function ExampleClientComponent() {
const segment = useSelectedLayoutSegment()
return <p>Active segment: {segment}</p>
}
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
export default function ExampleClientComponent() {
const segment = useSelectedLayoutSegment()
return <p>Active segment: {segment}</p>
}
Good to know:
- Since
useSelectedLayoutSegmentis a Client Component hook, and Layouts are Server Components by default,useSelectedLayoutSegmentis usually called via a Client Component that is imported into a Layout.useSelectedLayoutSegmentonly returns the segment one level down. To return all active segments, seeuseSelectedLayoutSegments- For catch-all routes, the matched segments are returned as a single joined string. For example, given
app/blog/[...slug]/page.js, calling fromapp/blog/layout.jswhen visiting/blog/a/b/creturns'a/b/c'.
const segment = useSelectedLayoutSegment(parallelRoutesKey?: string)
useSelectedLayoutSegment optionally accepts a parallelRoutesKey, which allows you to read the active route segment within that slot.
useSelectedLayoutSegment returns a string of the active segment or null if one doesn't exist.
For example, given the Layouts and URLs below, the returned segment would be:
| Layout | Visited URL | Returned Segment |
|---|---|---|
app/layout.js | / | null |
app/layout.js | /dashboard | 'dashboard' |
app/dashboard/layout.js | /dashboard | null |
app/dashboard/layout.js | /dashboard/settings | 'settings' |
app/dashboard/layout.js | /dashboard/analytics | 'analytics' |
app/dashboard/layout.js | /dashboard/analytics/monthly | 'analytics' |
For catch-all routes ([...slug]), the returned segment contains all matched path segments joined as a single string:
| Layout | Visited URL | Returned Segment |
|---|---|---|
app/blog/layout.js | /blog/a/b/c | 'a/b/c' |
When cacheComponents is enabled, useSelectedLayoutSegment may require a Suspense boundary. This depends on whether the active segment can be resolved during prerendering.
generateStaticParams: every route segment, including dynamic params, is known at build time. The active segment can be resolved during prerendering, so useSelectedLayoutSegment resolves on the server and no Suspense boundary is required.generateStaticParams: the param is a fallback param that is not known until request time. The active segment cannot be resolved during prerendering, so useSelectedLayoutSegment 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 useSelectedLayoutSegment is itself static. For example, a tab bar rendered in a parent 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 useSelectedLayoutSegment (or a parent) in a Suspense boundary with a fallback.
See Next.js encountered URL data in a Client Component outside of Suspense for full fix options and trade-offs.
You can use useSelectedLayoutSegment to create an active link component that changes style depending on the active segment. For example, a featured posts list in the sidebar of a blog:
'use client'
import Link from 'next/link'
import { useSelectedLayoutSegment } from 'next/navigation'
// This *client* component will be imported into a blog layout
export default function BlogNavLink({
slug,
children,
}: {
slug: string
children: React.ReactNode
}) {
// Navigating to `/blog/hello-world` will return 'hello-world'
// for the selected layout segment
const segment = useSelectedLayoutSegment()
const isActive = slug === segment
return (
<Link
href={`/blog/${slug}`}
// Change style depending on whether the link is active
style={{ fontWeight: isActive ? 'bold' : 'normal' }}
>
{children}
</Link>
)
}
'use client'
import Link from 'next/link'
import { useSelectedLayoutSegment } from 'next/navigation'
// This *client* component will be imported into a blog layout
export default function BlogNavLink({ slug, children }) {
// Navigating to `/blog/hello-world` will return 'hello-world'
// for the selected layout segment
const segment = useSelectedLayoutSegment()
const isActive = slug === segment
return (
<Link
href={`/blog/${slug}`}
// Change style depending on whether the link is active
style={{ fontWeight: isActive ? 'bold' : 'normal' }}
>
{children}
</Link>
)
}
// Import the Client Component into a parent Layout (Server Component)
import { BlogNavLink } from './blog-nav-link'
import getFeaturedPosts from './get-featured-posts'
export default async function Layout({
children,
}: {
children: React.ReactNode
}) {
const featuredPosts = await getFeaturedPosts()
return (
<div>
{featuredPosts.map((post) => (
<div key={post.id}>
<BlogNavLink slug={post.slug}>{post.title}</BlogNavLink>
</div>
))}
<div>{children}</div>
</div>
)
}
// Import the Client Component into a parent Layout (Server Component)
import { BlogNavLink } from './blog-nav-link'
import getFeaturedPosts from './get-featured-posts'
export default async function Layout({ children }) {
const featuredPosts = await getFeaturedPosts()
return (
<div>
{featuredPosts.map((post) => (
<div key={post.id}>
<BlogNavLink slug={post.slug}>{post.title}</BlogNavLink>
</div>
))}
<div>{children}</div>
</div>
)
}
| Version | Changes |
|---|---|
v13.0.0 | useSelectedLayoutSegment introduced. |