import { useNavigate } from 'react-router-dom';
import * as S from './GNB.style';
import { useState } from 'react';

const GNB = () => {
  const navigate = useNavigate();
  const [active, setActive] = useState<string>('home');
  const handldeActive = (label: string, path: string) => {
    setActive(label);
    navigate(path);
  };
  const navList = [
    { label: 'home', name: '홈', path: '/home', icon: null },
    { label: 'moment', name: '모멘트', path: '/moment', icon: null },
    { label: 'feed', name: '피드', path: '/feed', icon: null },
    { label: 'mypage', name: '마이', path: '/mypage', icon: null },
  ];

  return (
    <S.GNBLayout>
      {navList.map((nav) => (
        <S.NavItem
          key={nav.label}
          onClick={() => handldeActive(nav.label, nav.path)}
        >
          {active === nav.label ? <S.AciteTab /> : <S.UnActiveTab />}
          <S.NavLabelSpan>{nav.name}</S.NavLabelSpan>
        </S.NavItem>
      ))}
    </S.GNBLayout>
  );
};

export default GNB;

GNB(네비게이션바) 첫 구현 코드이다. 

useNavigate를 통해 경로 이동을 설정해주었고 useState를 통하여 아이콘의 상태를 관리하고 있다. 

그러나 해당 방식의 경우 url 에 직접 경로를 작성하여 이동하거나 새로고침을 할 경우 active 의 상태가 반영이 되지 않아 현재 페이지와 GNB 의 아이콘 활성화가 달라지는 오류가 존재한다. 

 

이에 NavLink를 사용해보라는 팀원의 리뷰를 받고 수정을 해보았다. 

https://reactrouter.com/start/library/navigating#navlink

 

Navigating | React Router

 

reactrouter.com

현재 활성된 상태의 네비게이션 링크를 표현하는 컴포넌트라고 한다.

설정한 경로에 해당하는 NavLink 컴포넌트가 활성화되면 active 상태가 되어 .active 라는 클래스 네임을 가지게 되며 이에 맞게 스타일을 설정할 수 있다. 

스타일은 className, style 속성, children 을 통하여 설정할 수 있다. 

 

현재는 styled-component를 통하여 페이지에 따라 요소를 렌더링하게 하였지만 추후에 아이콘을 통해 렌더링할 것이기 때문에 children 을 통하여 구현을 하였다. 

import { NavLink } from 'react-router-dom';
import * as S from './GNB.style';

const GNB = () => {
  const navList = [
    { label: 'home', name: '홈', path: '/home', icon: null },
    { label: 'moment', name: '모멘트', path: '/moment', icon: null },
    { label: 'feed', name: '피드', path: '/feed', icon: null },
    { label: 'mypage', name: '마이', path: '/mypage', icon: null },
  ];

  return (
    <S.GNBLayout>
      {navList.map((nav) => (
        <NavLink key={nav.label} to={nav.path}>
          {({ isActive }) => (
            <S.NavItem>
              {isActive ? <S.AciteTab /> : <S.UnActiveTab />}
              <S.NavLabelSpan>{nav.name}</S.NavLabelSpan>
            </S.NavItem>
          )}
        </NavLink>
      ))}
    </S.GNBLayout>
  );
};

export default GNB;

 

 

현재 피드 페이지에 있는 상태이고

개발자 도구를 통해 확인해 보면 active 라는 class 가 활성화된 것을 확인할 수 있다. 

 

평소 경로에 대한 이벤트를 작성할 때 useNavigate 를 주로 사용하였는데 공식 문서를 다시 살펴보니 키보드 이벤트 같은 유저 기능, 라벨링, 새 창 열기 등의 이유로 Link 나 NavLink 태그를 사용하는 것을 권장한다고 한다. 

특히 이번에 사용한 NavLink 는 메뉴바나 네비게이션바 구현에 최적화된 기능임을 느꼈다. 

그렇다면 Link 태그와 useNavigate 는 각각 어떨 때 사용하는가 ?

Link 는 보통 클릭 시 단순히 화면이 이동되는 경우에, 

useNavigate 는 페이지 전환과 더불어 추가적인 동작이 발생하는 경우에 사용을 권한다고 한다. 

폼을 제출하거나 조건에 따라 이동되는 경로가 다른 경우 등이 해당된다. 

728x90