
Active Link 를 만들기 위해 App router의 useSelectedLayoutSegment() 훅을 사용할 수 있다.
useSelectedLayoutSegment()는 클라이언트 컴포넌트에서 사용되는 훅으로, 호출된 레이아웃보다 한 수준 아래에 있는 segment를 반환한다.useSelectedLayoutSegments 사용layout이 속한 폴더를 기준으로 폴더가 같으면 null, 다르면 바로 아래있는 segment를 반환한다.useSelectedLayoutSegment()는 클라이언트 컴포넌트 훅이고, 레이아웃은 서버 컴포넌트이므로, useSelectedLayoutSegment()는 레이아웃으로 임포트된 클라이언트 컴포넌트를 통해서만 사용된다.page.tsx에서 클라이언트 컴포넌트를 임포트해서 useSelectedLayoutSegment() 사용하면, null을 반환한다.page.tsx에서 현재 url을 가져오고 싶다면 usePathname()을 사용하는 게 좋다.const segment = useSelectedLayoutSegment(parallelRoutesKey?: string)
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
export default function ExampleClientComponent() {
const segment = useSelectedLayoutSegment()
return <p>Active segment: {segment}</p>
}
useSelectedLayoutSegment
useSelectedLayoutSegments
useSelectedLayoutSegment()를 이용해 segment를 가져와 segment와 일치하는 Active Link 를 만들 수 있다.// app/blog/blog-nav-link.tsx
'use client'
import Link from 'next/link'
import { useSelectedLayoutSegment } from 'next/navigation'
export default function BlogNavLink({
slug,
children,
}: {
slug: string
children: React.ReactNode
}) {
// `/blog/hello-world`로 이동하면 선택된 레이아웃 세그먼트에 'hello-world'가 반환
const segment = useSelectedLayoutSegment()
const isActive = slug === segment
return (
<Link
href={`/blog/${slug}`}
// 링크 활성 상태에 따라 스타일 변경
style={{ fontWeight: isActive ? 'bold' : 'normal' }}
>
{children}
</Link>
)
}
// app/blog/layout.tsx
// 클라이언트 컴포넌트를 부모 레이아웃(서버 컴포넌트)에 가져오기
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>
)
}
현재 URL 경로 정보를 알 수 있는 다른 훅들에 대해서도 알아보자 !
usePathname은 대체 경로가 렌더링되거나 Next.js에 의해 페이지 디렉토리 페이지가 자동으로 정적으로 최적화되었을 때 및 라우터가 준비되지 않은 경우에 null을 반환한다.const pathname = usePathname()
// app/example-client-component.tsx
'use client'
import { usePathname } from 'next/navigation'
export default function ExampleClientComponent() {
const pathname = usePathname()
return <p>Current pathname: {pathname}</p>
}

useParams는 빈 객체를 반환한다.const params = useParams()
// app/example-client-component.tsx
'use client'
import { useParams } from 'next/navigation'
export default function ExampleClientComponent() {
const params = useParams<{ tag: string; item: string }>()
// 라우트 -> /shop/[tag]/[item]
// URL -> /shop/shoes/nike-air-max-97
// `params` -> { tag: 'shoes', item: 'nike-air-max-97' }
console.log(params)
return <></>
}

URLSearchParams.get() : 파라미터의 첫번째 value를 반환URLSearchParams.has() : 파라미터의 존재 여부 반환URLSearchParams.getAll() : 모든 파라미터의 value를 문자열로 반환URLSearchParams.keys() : 모든 파라미터의 key를 문자열로 반환URLSearchParams.entries() : 모든 파라미터의 key와 value를 문자열로 반환URLSearchParams.toString() : 현재 쿼리 스트링을 문자열로 반환const searchParams = useSearchParams()
'use client'
import { useSearchParams } from 'next/navigation'
export default function SearchBar() {
const searchParams = useSearchParams()
const search = searchParams.get('search')
// URL -> `/dashboard?search=my-project`
// `search` -> 'my-project'
return <>Search: {search}</>
}