[Next.js] useSelectedLayoutSegment를 활용하여 Active Link 만들기

문지은·2024년 3월 10일
0

Next.js - App Router

목록 보기
18/20
post-thumbnail

Active Link 를 만들기 위해 App router의 useSelectedLayoutSegment() 훅을 사용할 수 있다.

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 vs useSelectedLayoutSegments

  • useSelectedLayoutSegment

  • useSelectedLayoutSegments

Active Link 만들기

  • useSelectedLayoutSegment()를 이용해 segment를 가져와 segment와 일치하는 Active Link 를 만들 수 있다.
  • 클라이언트 컴포넌트로 활성 세그먼트에 따라 스타일이 변경되는 NavLink 컴포넌트 만들기
// 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

  • 클라이언트 컴포넌트 훅으로, 현재 URL의 경로명을 반환한다.
  • 서버 컴포넌트에서 현재 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

  • 클라이언트 컴포넌트 훅으로 현재 URL에 의해 채워진 라우트의 동적 매개변수를 객체 형태로 반환한다.
  • 속성의 이름은 세그먼트의 이름이며, 속성의 값은 세그먼트에 채워진 값이다.
  • 라우트에 동적 매개변수가 없는 경우 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 <></>
}

useSearchParams

  • 클라이언트 컴포넌트 훅으로, 현재 URL의 쿼리 문자열에 대한 다양한 메서드를 제공한다.
    • 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}</>
}
profile
코드로 꿈을 펼치는 개발자의 이야기, 노력과 열정이 가득한 곳 🌈

0개의 댓글