Front-End/Project

[WizSched] react-router-dom v6 Outlet 적용

Y0ungZ 2024. 1. 11. 02:53
🍀 목차
문제
Outlet
적용하기

 

 

문제

 지금까지 프로젝트에서 Header가 고정된 레이아웃을 만들 때 app.tsx에서 Header를 선언하여 사용했었다. 이 구조를 다시 보니 라우팅을 관리하는 컨테이너와 UI 컴포넌트가 뒤섞여 있어 읽기 어렵다고 생각했다. 또한 프로젝트에 여러 API를 활용하기에 페이지마다 Header가 달라질 수 있다 판단했다. 그럴때마다 pathname을 이용해 조건문을 작성하여 렌더링 여부를 판단하기는 번거롭다고 느꼈다. 

 

옛날 프로젝트 사진
2021년 프로젝트

 

 이를 어떻게 개선할 수 있을까 검색해 보다가 react-router-dom(v6)의 Outlet을 알게 되었다.

 

 

Outlet

 Outlet은 중첩 라우트 구조에서 자식 라우트를 표시하는 데 사용된다. 부모 라우트의 특정 위치에서 자식 라우트를 렌더링 할 수 있도록 도와준다. 일반적으로 특정 컴포넌트 내의 다른 하위 컴포넌트의 자리를 지정하는 데 활용된다. 

 

중첩 라우트 구조
하나의 라우트 안에 또 다른 라우트를 중첩하여 사용하는 것. 
페이지의 일부를 독립적으로 관리할 수 있어 재사용성을 향상시킬 수 있다. 중첩 라우트 구조에서 부모 라우트는 특정 경로에 대한 레이아웃 및 공통 컴포넌트가 들어가고, 그 안에 자식 라우트들이 중첩된다. 각 자식 라우트는 부모 라우트 경로에 추가되어 특정 컴포넌트를 렌더링 한다.

<Routes>
      <Route path="/" element={<Dashboard />}>
        <Route
          path="messages"
          element={<DashboardMessages />}
        />
        <Route path="tasks" element={<DashboardTasks />} />
      </Route>
</Routes>​
//https://reactrouter.com/en/main/components/outlet

 위 코드에서 경로 /DashBoard 컴포넌트가, 경로 /messagesDashboardMessages 컴포넌트로 중첩되어 렌더링, 경로 /tasksDashboardTasks 컴포넌트로 중첩되어 렌더링 된다.

 

 

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>

      {/* This element will render either <DashboardMessages> when the URL is
          "/messages", <DashboardTasks> at "/tasks", or null if it is "/"
      */}
      <Outlet />
    </div>
  );
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<Dashboard />}>
        <Route
          path="messages"
          element={<DashboardMessages />}
        />
        <Route path="tasks" element={<DashboardTasks />} />
      </Route>
    </Routes>
  );
}

 

 

 해당 코드로 확인해보면 루트 경로의 결과는 아래와 같이 나온다.

 

경로 /

 

경로 /messages는 아래와 같이,

경로 /messages

 

경로 /tasks는 아래와 같다.

 

경로 /tasks

 

 

const Layout = () => {
  return (
    <>
      <Header />
      <Outlet />
      <Footer />
    </>
  );
};

export default Layout;

 

 이를 활용하여 다양한 Layout을 만들어 관리할 수 있다.

 


적용하기

 createBrowserRouter를 이용해 router설정을 해준다. (참고 문서)

 

//router.tsx
const router = createBrowserRouter([
  {
    path: ROUTE_PATH.ROOT, // '/'
    element: <Layout />,
    children: [
      {
        path: ROUTE_PATH.LOGIN, // 'login'
        element: <LoginPage />,
      },
    ],
  },
]);

export default router;

//index.tsx에 RouterProvider 추가
ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>,
);

 

 

path ROOT의 children으로 들어간 element들은 모두 Layout을 거치게 된다.

 

header가 포함된 layout을 만들었다.
Layout

 

Layout은 위에 Header가 포함된 구조이다.

 

Header 로그인 버튼. 클릭 시 /login으로 간다.
Header 로그인 버튼

 

Header에 포함된 로그인 버튼을 클릭하면 /login으로 간다.

 

LoginPage. Header가 포함되어 있지 않다.
LoginPage. Header가 포함되어 있지 않다.

 

LoginPage에는 Header가 포함되어 있지 않다.

 

헤더가 포함된 매인 페이지. 로그인을 클릭하려 한다.
로그인을 클릭해 보자.
헤더가 포함된 로그인 페이지로 이동했다.

 

 

 이제 다양한 레이아웃을 커스텀하기 편해졌다. ✨

 

 

참고자료

https://reactrouter.com/en/main