[React] React-Router-Dom v6 주요 기능들

hyeondoonge·2023년 8월 23일
0

React-Router-Dom을 사용하다보면 필요할 때마다 문서에서 가져다쓰는 경우가 많다. 왜 써야하는지 모르고, 쓰라고하니 쓰는 것과 같은 수동적인 개발 방식은 좋지 않은 학습 방법이다. 또한 그러다보면 유용한 기능들이 있는데 놓치게되어 쓰던 것만 쓰게되는 상황이 발생한다.

주도적으로 내가 자주 사용했던 React-Router-Dom 기능이 구체적으로 어떤 것이고, 또 다른 유용한 기능들은 어떤 것들이 있는지 정리하며 살펴보고자 한다.

참고로 React-Router-Dom v6.15.0 기준으로 작성했다.

Router

Route 정보를 통해 현재 url, 히스토리 관리 등을 수행한다.

이전 버전에서는 BrowserRouter, HashRouter 등을 이용해 라우터를 정의할 수 있는데, createBrowserRouter, createHashRouter를 사용하게되면 Data API를 통해 Route에 loaders, actions, fetchers와 같은 유용한 기능을 사용해, 필요한 요구사항을 빠르게 구현할 수 있다.

BrowserRouter

  • web 프로젝트 시 createBrowserRouter 사용이 권고된다
  • 해시 URL 대신 Full URL을 사용한다.
  • 내부적으로 DOM History API을 이용해 URL을 업데이트하고 history 스택을 관리한다

routes

createBrowserRouter의 매개변수로, route객체를 주입할 수 있다.

browser router 말고도 HashRouter, MemoryRouter 등이 있다. 다른 Router들은 어디 사용되는 걸까?
그 중 MemoryRoutercreateMemoryRouter를 통해 생성된다. 브라우저 history를 사용하지 않고 memory 내부에서 별개의 history stack을 관리한다. 테스트 및 컴포넌트 개발 도구에 유용하며 브라우저가 아닌 환경에서 React 라우터 실행을 위해 사용될 수 있다.

Route

  • URL과 컴포넌트를 연결한다.
  • 부모, 자식 관계에 있는 Route 선언도 가능하다. 즉 중첩 Route를 작성하여 중복하는 URL의 Prefix 를 표현할 수 있다.

• Path

컴포넌트 그려낼 URL 지정한다. :dynamic segment를 나타낸다. path가teams/:teamsId 일 경우 teamsId에는 여러 값들이 허용되고 teams/1 teams/5 등의 입력이 해당 경로에 매핑된다. 매핑된 컴포넌트에서 teamsId에 대한 값을 얻기위해서 useParams 훅을 이용해 접근한다.

• Splats

*(star) segmenet를 사용할 경우 하위 경로가 어떻게 되든지 모든 경로에 대응된다. path가 teams/* 일 경우 teams/3, teams/team/3 등의 경로에 매핑된다.

dynamic segmenet와 동일하게 useParams 를 사용해 param에 접근한다.

• loader

컴포넌트를 렌더링 하기 이전에 수행되고, 수행결과를 컴포넌트에 전달한다.

예를 들어 화면이 렌더링 되기 전에 인증된 사용자인지를 검사한 후, 다른 페이지로 리다이렉트할지 또는 화면을 렌더링할지 동작할 수 있다.

• element / Component

url에 대응하여 렌더링할 컴포넌트를 지정한다.

• errorElement / ErrorBoundary

컴포넌트 렌더링 중 에러가 발생하면 정상적인 컴포넌트 대신 그려질 컴포넌트를 지정한다.

위 element / Component 처럼 엘리먼트를 생성하는 주체가 개발자인지 React Router인지에 차이가 있다.

• lazy

라우트를 기준으로 code-splitting을 제공한다.

lazy 사용을 위해 Route의 lazy 속성에 아래처럼 모듈을 import한다. 그리고 그려낼 컴포넌트, 이외에 필요한 loader, error boundary등 기능을 a 모듈내에서 export 한다.

<Route path="/" element={<Layout />}>
    <Route path="a" lazy={() => import("./a")} />
    <Route path="b" lazy={() => import("./b")} />
  </Route>
// ./a
export async function loader({ request }) {
  let data = await fetchData(request);
  return json(data);
}

export function Component() {
  let data = useLoaderData();

  return (
    <>
      <h1>You made it!</h1>
      <p>{data}</p>
    </>
  );
}

Outlet

Parent route element에 outlet을 선언하면 그곳에 child route elements들이 그려지게된다. 이때 path는 전달하지않는다.

여러 페이지에서 공통적으로 사용되는 헤더, 목차 등을 Parent에 그려주고 Outlet을 선언하면 유지보수성이 개선된 코드를 작성할 수 있다.

const router = createBrowserRouter([
  {
    path: '/',
    element: <PageLayout />,
    children: [
      {
        path: ROUTE_FORM_URL,
        element: <RequestFormPage />
      },
      {
        path: ROUTE_REQUESTS_URL,
        element: <RequestsPage />
      }
    ]
  },
]);
// PageLayout.tsx
export default function PageLayout() {
  return (
    <StyledPageLayout> 
      <StyledTOC> {/* 목차 컴포넌트*/}
        <StyledLink to={ROUTE_FORM_URL}>요청</StyledLink>
        <StyledLink to={ROUTE_REQUESTS_URL}>요청 목록</StyledLink>
      </StyledTOC>
      <Outlet /> {/* 이곳에 하위 컴포넌트가 주입된다*/}
    </StyledPageLayout>
  );
}

컴포넌트를 반환하면 현재 location을 변경한다.

<Naviagte to=`${URL}` />

🪄TIP useNavigate훅을 사용해서 경로이동이 가능한 navigate함수를 사용할 수 있다.

• replace

history 스택의 현재 경로를 대체, 대체당하는 경로는 스택에 기록되지 않게 된다. (Link에 포함된 속성과 동일)

클릭 시 새로운 페이지로 이동하는 동작을 수행. 내부적으로 anchor 요소 사용하는 요소다.

<Link to={ROUTE_LOGIN_URL}>로그인하기</Link>

• replace

history 스택의 현재 경로를 대체, 대체당하는 경로는 스택에 기록되지 않게 된다.

active, pending 에 따라 스타일을 지정한다. Navigation 바, 탭 등을 구현할 때 유용하다.

예를 들어 현재 선택된 페이지의 링크를 하이라이팅하는 것에 쓰인다.

<StyledLink to={ROUTE_FORM_URL}>요청</StyledLink>

const StyledLink = styled(NavLink)`
  color: white;
  text-decoration: none;
  padding: 10px;
  border-radius: 10px;
  &:hover {
    background-color: #4898b3;
  }
  &.active {
    background-color: #4898b3;
  }
`;

• active

현재 링크가 active한 상태이면, active 클래스명이 컴포넌트에 자동으로 추가됨, 따라서 컴포넌트에 active 클래스에 대한 스타일만 지정하기만 하면된다.

0개의 댓글