triplus) 서브라우트-여행관리페이지 navbar 만들기

하쿄이_hakyoiii·2021년 12월 27일

프로젝트일지

목록 보기
5/12

여행관리 페이지

여행관리페이지 스크린샷

여행관리 페이지의 UI는 위와 같다.

저기서 서브라우팅에 따른 Nav바를 만들어줘야 하는데, active라는 상태를 props로 전달해서 눌릴때 확인할 수 있도록 만들어줬다.

서브라우팅

서브라우팅이란 라우트 내부에 라우트를 만드는 것을 말한다.

메인 라우트가 /management이고, /management안에 /management/tourlist가 있는 형식으로 구현을 해주었다. 메인 라우트를 여러개 만드는 대신 서브라우트를 이용하는 이유는 검색엔진최적화에도 도움이 되고, 복잡한 라우트들을 메인과-브랜치로 나누어서 정리할 수 있기 때문이다.

react-router-dom의 v6에서는 outlet으로 쉽게 서브라우팅을 해줄 수있다.

<Route path='/management' element={<ManagementPage />}>
          <Route path='tourlist' element={<TourManagementPage />} />
</Route>

우선 app.jsx에서 /management라고 되어있는 메인 라우트 안에 서브로 넣어줄 라우트를 만들고 컴포넌트를 연결해주면 된다.

이후 managementPage라는 메인 라우트 컴포넌트에서 outlet을 이용해 서브로 확장하여 만들어 주면 된다.

<Background pathName={pathname}>
   <ManageNav pathName={pathname.pathname} clicked={clicked} />
   <Outlet />
    {pathname === '/management' && (
   <ManageCtn>
   <ManageSection
    handleCreateClick={handleCreateClick}
    guideInfo={guideInfo}
    applicantInfo={applicantInfo}
    isLoading={isLoading}
    />
  </ManageCtn>
 )}
</Background>

중첩 라우팅에 outlet컴포넌트를 사용하게 되면, management에 있는 컴포넌트들이 서브라우트에도 들어가게 된다. 그래서 navbar의 공유가 가능하다.

하지만 여기서 문제가 있었는데, management navbar뿐만이 아니라 management에 있는 모든 컴포넌트들이 들어가게 되어서, pathname이 management일때만 들어가는 컴포넌트들을 &&연산자를 이용해 따로 정의해 두었다.

상태를 이용해 navbar관리하기

navbar를 이용해 해당 페이지에 들어가는 경우 해당 Link의 css를 다르게 해주는 작업이 필요했다. 이때, active라는 상태를 styled-components에 props로 전달해서 active가 true일 때는 폰트 굵기와, 밑에 경계선을 주어 구분을 해주었다.

ManagementPage컴포넌트

const [clicked, setClick] = useState({
    management: true,
    managementtourlist: false,
  });
...
중략
useEffect(() => {
    setIsLoading(true);

    const path = pathname.split('/').join('');
    if (path === 'management') {
      setClick({ management: true, managementtourlist: false });
    } else {
      setClick({ management: false, managementtourlist: true });
    }
}
...
중략
<ManageNav pathName={pathname.pathname} clicked={clicked} />

ManageNav컴포넌트


const LinkBtn = styled(NoBorderBtn)`
  color: ${({ theme }) => theme.color.lightGray};
  font-weight: 400;
  font-size: 1.1rem;
  box-sizing: border-box;
  height: 2rem;
  line-height: 2rem;
  ${({ active }) =>
    active &&
    css`
      font-weight: 600;
      font-size: 1.2rem;
      color: #fff;
      /* border-bottom: 1px solid #fff; */
      box-sizing: border-box;
      & span {
        border-bottom: 1px solid #fff;
      }
    `}
  &:hover {
    font-weight: 600;
    font-size: 1.2rem;
    color: #fff;
    /* border-bottom: 1px solid #fff; */
    box-sizing: border-box;
    & span {
      border-bottom: 1px solid #fff;
    }
  }
  &:active {
    font-weight: 600;
    font-size: 1.2rem;
    color: #fff;
    /* border-bottom: 1px solid #fff; */
    box-sizing: border-box;
    & span {
      border-bottom: 1px solid #fff;
    }
  }
`;
export default function ManageNav(props) {
  const { clicked } = props;
  return (
    <NavCtn>
      <Link to='/management'>
        <LinkBtn className='guideBtn' active={clicked.management}>
          <span>가이드 모드</span>
        </LinkBtn>
      </Link>
      <Link to='/management/tourlist'>
        <LinkBtn className='touristBtn' active={clicked.managementtourlist}>
          <span>여행자 모드</span>
        </LinkBtn>
      </Link>
    </NavCtn>
  );
}

NavBar안에 Link로 라우트를 다르게 주었기 때문에 Link를 클릭할 때마다 management페이지의 useEffect함수가 실행되고, useEffect가 실행될 때마다 path를 이용해 active설정을 해주었다.

받아온 clicked상태를 active라는 이름으로 styled-components에 전달하여 active일때의 css를 다르게 적용해주면 완성이다.

완성된 navbar의 모습이다.

navbar스크린샷

마주친 이슈

outlet을 이용한 서브라우트 상속문제

outlet을 사용해 navbar를 공유하는 서브 페이지를 만드는 게 목표였다. 처음엔 구현이 잘 된 것 같았으나, 여행자모드에서 스크롤을 내리면 가이드 모드에 있던 컴포넌트들이 여행자모드에도 들어가 있는 걸 볼 수 있었다.
outlet은 메인 라우트에 있던 컴포넌트들을 서브 라우트에서도 렌더링이 되게 만드는데, 이를 몰라서 겪었던 문제였다.

<Background pathName={pathname}>
   <ManageNav pathName={pathname.pathname} clicked={clicked} />
   <Outlet />
    {pathname === '/management' && (
   <ManageCtn>
   <ManageSection
    handleCreateClick={handleCreateClick}
    guideInfo={guideInfo}
    applicantInfo={applicantInfo}
    isLoading={isLoading}
    />
  </ManageCtn>
 )}
</Background>

Outlet 밑에 pathname이 management일 경우에만 나오도록 조건을 걸어두어 해결했다.

profile
Hello I'm front-end engineer hakyoung song!

0개의 댓글