UNPKG

next

Version:

The React Framework

180 lines (142 loc) • 6.23 kB
--- title: useSelectedLayoutSegment description: API Reference for the useSelectedLayoutSegment hook. --- `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. ```tsx filename="app/example-client-component.tsx" switcher 'use client' import { useSelectedLayoutSegment } from 'next/navigation' export default function ExampleClientComponent() { const segment = useSelectedLayoutSegment() return <p>Active segment: {segment}</p> } ``` ```jsx filename="app/example-client-component.js" switcher 'use client' import { useSelectedLayoutSegment } from 'next/navigation' export default function ExampleClientComponent() { const segment = useSelectedLayoutSegment() return <p>Active segment: {segment}</p> } ``` > **Good to know**: > > - Since `useSelectedLayoutSegment` is a [Client Component](/docs/app/getting-started/server-and-client-components) hook, and Layouts are [Server Components](/docs/app/getting-started/server-and-client-components) by default, `useSelectedLayoutSegment` is usually called via a Client Component that is imported into a Layout. > - `useSelectedLayoutSegment` only returns the segment one level down. To return all active segments, see [`useSelectedLayoutSegments`](/docs/app/api-reference/functions/use-selected-layout-segments) > - For [catch-all](/docs/app/api-reference/file-conventions/dynamic-routes#catch-all-segments) routes, the matched segments are returned as a single joined string. For example, given `app/blog/[...slug]/page.js`, calling from `app/blog/layout.js` when visiting `/blog/a/b/c` returns `'a/b/c'`. ## Parameters ```tsx const segment = useSelectedLayoutSegment(parallelRoutesKey?: string) ``` `useSelectedLayoutSegment` _optionally_ accepts a [`parallelRoutesKey`](/docs/app/api-reference/file-conventions/parallel-routes#with-useselectedlayoutsegments), which allows you to read the active route segment within that slot. ## Returns `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'` | ## Examples ### Creating an active link component 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: ```tsx filename="app/blog/blog-nav-link.tsx" switcher '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> ) } ``` ```jsx filename="app/blog/blog-nav-link.js" switcher '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> ) } ``` ```tsx filename="app/blog/layout.tsx" switcher // 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> ) } ``` ```jsx filename="app/blog/layout.js" switcher // 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 History | Version | Changes | | --------- | -------------------------------------- | | `v13.0.0` | `useSelectedLayoutSegment` introduced. |