s e o p p o r t . l o g

Today I Learned

[Next.js] navBar의 Active 스타일링 하기

Seo Ji Won 2024. 3. 13. 22:38

리액트를 쓸때는 라우터의 Link 태그에 기본적으로 active 클래스가 내장되어 있기 때문에 간편하게 active 스타일링을 지정할 수 있었다.

하지만 Next의 Link 태그에는 그러한 기능이 없기 때문에 pathName을 이용해서 네비게이션 바를 구현해보게 되었다.

 

처음에는 useState를 사용해서 네비게이션바의 아이템을 클릭하면 아이템과 state를 비교하여 조건부 스타일링을 구현했었는데, 그렇게 하니까 사용자가 네비게이션바가 아닌 다른 버튼을 통해 다른 페이지로 이동했을 때 네비게이션 바에는 반영되지 않아 문제가 있던 상황이었다.

원했던 것은 사용자가 현재 위치한 페이지가 navBar와 동기화되는 것이었다.

 

1. Nav Bar 생성

우선 네비게이션 아이템 리스트를 만들고 map으로 링크를 생성한다.

const navList = ['Home', 'About', 'Report', 'Todo-CSR', 'Todo-SSR'];
navList.map((item, idx) => (
          <Link key={idx}>
            {item}
          </Link>

 

2. usePathname 훅

usePathname은 현재 브라우저의 경로를 반환하는 Next.js의 훅이다. 이 훅을 사용하면 사용자가 위치한 현재 페이지의 경로를 얻을 수 있다. 이 정보를 활용해 해당 페이지에 대응하는 NavBar 링크에 스타일을 적용할 수 있다.

  const pathName = usePathname();

만약 'localhost:3000/home'의 주소에서 pathName을 콘솔에 찍어보면 '/home' 이 찍히게 된다.

 

3. 조건부 스타일링

className에 템플릿 리터럴을 사용해 조건부로 스타일을 적용한다. 경로명이 현재 pathName과 일치할 경우 'bg-indigo-300' 클래스를 추가하여 해당 링크에 배경색을 적용한다. 

<Link
  key={idx}
  className={`flex items-center justify-center w-20 h-10 rounded-lg mr-10
            ${`/${item.toLocaleLowerCase()}` === pathName ? 'bg-indigo-300' : ''}`}
  href={`/${item.toLocaleLowerCase()}`}
>
  {item}
</Link>;

 

 

다음은 전체 코드이다.

import Link from 'next/link';
import { usePathname } from 'next/navigation';
import React from 'react';

const NavBar = () => {
  const navList = ['Home', 'About', 'Report', 'Todo-CSR', 'Todo-SSR'];
  const pathName = usePathname();

  return (
    <nav>
      <div className='flex bg-indigo-50 h-16 items-center justify-end'>
        <div className='mr-auto ml-10 text-2xl font-medium'>Meow Inc.</div>
        {navList.map((item, idx) => (
          <Link
            key={idx}
            className={`flex items-center justify-center w-20 h-10 rounded-lg mr-10
            ${`/${item.toLocaleLowerCase()}` === pathName ? 'bg-indigo-300' : ''}`}
            href={`/${item.toLocaleLowerCase()}`}
          >
            {item}
          </Link>
        ))}
      </div>
    </nav>
  );
};

export default NavBar;