SUIN

react-router-dom v6 <NavLink> 적용해보기 본문

React

react-router-dom v6 <NavLink> 적용해보기

choi suin 2022. 12. 28. 19:35
728x90

 

 

NavLink v6.6.1

Type declarationdeclare function NavLink( props: NavLinkProps ): React.ReactElement; interface NavLinkProps extends Omit< LinkProps, "className" | "style" | "children" > { caseSensitive?: boolean; children?: | React.ReactNode | ((props: { isActive: boolean

reactrouter.com

프로젝트의 sideNav를 구현하는 중  router-dom NavLink를 활용하여 페이지 이동과 스타일링을 구현해 보았다.

 


조건

-  5개의 Link 중  3개->페이지 이동 / 2개- 전역모달 구현

모달이 열리는 링크의 스타일은 isActive 상태가 false 

- 모바일사이즈의 경우  시 링크는 총 5개 -> 3개 변경 


import * as t from "./asideNav.style";
import { useState } from "react";
import { ListType } from "./asideNav.type";
import WithdrawalModal from "../../modal/withdrawalModal/WithdrawalModal";
import UserInfoModal from "../../modal/userInfoModal/UserInfoModal";
import { useViewport } from "../../../hooks/useViewport";



export default function AsideNav() {
  const viewport = useViewport();
  return viewport > 990 ? <Desktop /> : <Mobile />;
}

 

const desktopList: ListType[] = [
  { id: 1, name: "주문 조회", path: "mypage" },
  { id: 2, name: "위시 리스트", path: "wish" },
  { id: 3, name: "취소 조회", path: "cancel" },
  { id: 4, name: "정보 수정", path: "modal" },
  { id: 5, name: "회원탈퇴", path: "modal" },
];

// 데스트탑 
const Desktop = () => {
  const [withdrawaIsOpen, setWithdrawaIsOpen] = useState<boolean>(false);
  const [userInfoIsOpen, setUserInfoIsOpen] = useState<boolean>(false);
  const withdrawal = withdrawaIsOpen && (
    <WithdrawalModal
      isOpen={withdrawaIsOpen}
      handleClose={() => setWithdrawaIsOpen(false)}
    />
  );
  const userInfo = userInfoIsOpen && (
    <UserInfoModal
      isOpen={userInfoIsOpen}
      handleClose={() => setUserInfoIsOpen(false)}
    />
  );
  const navClickEvent = (
    list: ListType,
    event: React.MouseEvent<HTMLAnchorElement, MouseEvent>
  ) => {
    list.path === "modal" && event.preventDefault();
    list.name === "회원탈퇴" && setWithdrawaIsOpen(!withdrawaIsOpen);
    list.name === "정보 수정" && setUserInfoIsOpen(!userInfoIsOpen);
  };
  return (
    <>
      {withdrawal}
      {userInfo}
      <t.DesktopNavBox>
        {desktopList.map((list) => (
          <ul key={list.id}>
            <li>
              <t.Nav
                to={list.path}
                onClick={(e) => navClickEvent(list, e)}
                className={({ isActive }) => isActive && "active"}
              >
                {list.name}
              </t.Nav>
            </li>
          </ul>
        ))}
      </t.DesktopNavBox>
    </>
  );
};
const MobileList: ListType[] = [
  { id: 1, name: "주문 조회", path: "mypage" },
  { id: 2, name: "위시 리스트", path: "wish" },
  { id: 3, name: "취소 조회", path: "cancel" },
];

//모바일
const Mobile = () => {
  const navClickEvent = (
    list: ListType,
    event: React.MouseEvent<HTMLAnchorElement, MouseEvent>
  ) => {
    list.path === "modal" && event.preventDefault();
  };
  return (
    <>
      {MobileList.map((list) => (
        <t.MobileNavBox key={list.id}>
          <t.Nav
            to={list.path}
            onClick={(e) => navClickEvent(list, e)}
            className={({ isActive }) => isActive && "active"}
          >
            {list.name}
          </t.Nav>
        </t.MobileNavBox>
      ))}
    </>
  );
};

 

처음에는 페이지 이동이 필요한 구간만 NavLink를 적용하고 모달의 경우 링크 없이 별도로 만들어야 할까 고민했었다.

그렇게 돼버리면 코드가 길어지게 되며 가독성이 떨어진다고 생각했고 모달의 경우 별도로 이벤트를 막아버리는 방법을 생각했다.

list의 객체들을 map을 통해 <NavLink>를 생성하고 모달의 경우는 클릭 시 모달에도 클릭 시 활성되는 스타일링은 이벤트 클릭을 제외하며 각각의 모달을 연결하여 적용해 주었다. 

 

 

주문조회, 위시리스트, 취소조회의 경우 클릭 시 해정보 경로에 있다면 스타일이 활성되며

수정, 회원탈퇴에는 클릭 시  하단 스타일이 따로 적용되지 않고 모달이 열리는 것을 확인할 수 있다.