React Router v6 Tutorial - Nested Routes

homewiz·2023년 11월 14일
0

CRA create react app

목록 보기
6/6
post-thumbnail

intro

중첩 라우팅 하는 법에 대해 소개한다.

사전 작업

이전 문서에서 App.jsx 있는 컴포넌트들을 .jsx로 분리한다.

src/App.jsx
Navigation => src/navigation/index.jsx
Home => src/pages/Home/index.jsx
Category1 => src/pages/Category1/index.jsx
Category2 => src/pages/Category2/index.jsx
NotFound => src/NotFound.jsx

// App.jsx
import React from "react";
import {BrowserRouter as Router, Routes, Route} from "react-router-dom";
import Home from "@/pages/Home";
import Category1 from "@/pages/Category1";
import Category2 from "@/pages/Category2";
import NotFound from "@/pages/NotFound";
import Navigation from "@/navigation";

const App = () => {
  return (
    <div className="flex flex-row justify-center min-h-screen">
      <div className="w-[1080px]">
        <Router>
          <Navigation className="bg-blue-200 h-32 flex items-center" />
          <div className="bg-blue-50">
            <Routes>
              <Route path="/" element={<Home />} />
              <Route path="/category1" element={<Category1 />} />
              <Route path="/category2" element={<Category2 />} />
              <Route path="*" element={<NotFound />} />
            </Routes>
          </div>
        </Router>
      </div>
    </div>
  );
};

export default App;

How to handle nested routes

중첩 라우팅은 쉽게 말해 route page 안에 navigation 메뉴가 있는 경우이다.
GNB
 |– Category Link 1 – Sub Navigation Bar (Menu)
   |– Page Link 1
   |– Page Link 2
 |– Category Link 2 – Sub Navigation Bar (Menu)
   |– Page Link 1
   |– Page Link 2
Category1 page에서 하위 페이지를 이동 하는 경우 Outlet component를 이용해 Page가 랜더링된다.

// App.jsx
import React from "react";
import {BrowserRouter as Router, Routes, Route} from "react-router-dom";
import Home from "@/pages/Home";
import Category1 from "@/pages/Category1";
import Category2 from "@/pages/Category2";
import NotFound from "@/pages/NotFound";
import Navigation from "@/navigation";

const Page1 = () => {
  return <div>Page name is page1</div>;
};

const Page2 = () => {
  return <div>Page name is page2</div>;
};

const App = () => {
  return (
    <div className="flex flex-row justify-center min-h-screen">
      <div className="w-[1080px]">
        <Router>
          <Navigation className="bg-blue-200 h-32 flex items-center" />
          <div className="bg-blue-50">
            <Routes>
              <Route path="/" element={<Home />} />
              - <Route path="/category1" element={<Category1 />} />
              + <Route path="/category1" element={<Category1 />}>
              +  <Route index element={<Page1 />} />
              +  <Route path="/category1/page2" element={<Page2 />} />
              + </Route>
              <Route path="/category2" element={<Category2 />} />
              <Route path="*" element={<NotFound />} />
            </Routes>
          </div>
        </Router>
      </div>
    </div>
  );
};

export default App;

...
// src/pages/Cetegory1/index.jsx
import {Outlet} from "react-router-dom";

const Category1 = () => {
  return (
    <div>
      Category 1 {">>"} <Outlet /> => Outlet 추가
    </div>
  );
};
export default Category1;

컴포넌트에 하위 route들이 랜더링 된다.

  • localhost:3000/category1 =>Category1과 하위 Page1 출력

  • localhost:3000/category1/page2 => Category1과 하위 Page2 출력

// error code
<Route path="/page2" element={<Page2 />} />
// good 
<Route path="/category1/page2" element={<Page2 />} />

* 주의사항: 하위 route의 path는 반드시 상위 path를 같이 기재 해줘야 한다.
Uncaught runtime errors:
ERROR
Absolute route path "/page2" nested under path "/category1" is not valid. An absolute child route path must start with the combined path of all its parent routes.


Category1/index.jsx에 메뉴를 구현

import React from "react";
import {Outlet, Link} from "react-router-dom";

const Category1 = () => {
  return (
    <React.Fragment>
      <div className="flex flex-row px-10 py-2 border-b font-bold space-x-2">
        <Link to={`/category1`}>Page1</Link>
        <Link to={`/category1/page2`}>Page2</Link>
      </div>
      <div className="flex flex-row">
        Category1 {">>"}
        <Outlet />
      </div>
    </React.Fragment>
  );
};

export default Category1;

  • page1, page2를 눌러 변경을 확인하자.

Accessing URL parameters and dynamic parameters of a route

 <Route path="/category1/page2" element={<Page2 />} />

path="/category1/page2" 와 같이 정적 경로 구현외에

 <Route path=":slug" element={<Page2 />} />

":slug" 와 같이 동적 파라미터 경로를 설정 하는 방법에 대해 알아 보자.

// App.jsx
...
import {BrowserRouter as Router, Routes, Route, useParams} from "react-router-dom";
...
const Page3 = () => {
  const {slug} = useParams(); // hook을 이용하여 slug값을 받는다.

  return (
    <React.Fragment>
      <div>this is dynamic {slug} </div> {/* 슬러그 값을 출력한다. */}
    </React.Fragment>
  );
};
...

- <Route path="/category2" element={<Category2 />} /> 
  
+ <Route path="/category2" element={<Category2 />}>
+  <Route path=":slug" element={<Page3 />} /> // dynamic parameter
+ </Route>
  
...

위와 같이 dinamic parameter path를 잡아 준다.

// src/pages/Category2/index.jsx
import React from "react";
import {Outlet, Link} from "react-router-dom";

const Category2 = () => {
  return (
    <React.Fragment>
      <div className="flex flex-row px-10 py-2 border-b font-bold space-x-2">
        <Link to={`/category2/page3`}>Page3</Link>
        <Link to={`/category2/page4`}>Page4</Link>
      </div>
      <div className="flex flex-row">
        Category2 {">>"}
        <Outlet />
      </div>
    </React.Fragment>
  );
};

export default Category2;

Category2에 page3, 4에대한 링크 및 출력용 Outlet 을 입력.

page3, Page4 메뉴 이동 값을 확인한다.


다음 문서에서는 useRoute hook을 이용하여 소스를 깔끔하게 관리 하는 법에 대해 작성한다.


Source

// App.jsx
import React from "react";
import {BrowserRouter as Router, Routes, Route, useParams} from "react-router-dom";

import Home from "@/pages/Home";
import Category1 from "@/pages/Category1";
import Category2 from "@/pages/Category2";
import NotFound from "@/pages/NotFound";
import Navigation from "@/navigation";

const Page1 = () => {
  return <div>Page name is page1</div>;
};

const Page2 = () => {
  return <div>Page name is page2</div>;
};

const Page3 = () => {
  const {slug} = useParams(); // hook을 이용하여 slug값을 받는다.

  return (
    <React.Fragment>
      <div>this is dynamic {slug} </div> {/* 슬러그 값을 출력한다. */}
    </React.Fragment>
  );
};

const App = () => {
  return (
    <div className="flex flex-row justify-center min-h-screen">
      <div className="w-[1080px]">
        <Router>
          <Navigation className="bg-blue-200 h-32 flex items-center" />
          <div className="bg-blue-50">
            <Routes>
              <Route path="/" element={<Home />} />
              <Route path="/category1" element={<Category1 />} />
              <Route path="/category1" element={<Category1 />}>
                <Route index element={<Page1 />} />
                <Route path="/category1/page2" element={<Page2 />} />
              </Route>
              <Route path="/category2" element={<Category2 />}>
                <Route path=":slug" element={<Page3 />} />
              </Route>
              <Route path="*" element={<NotFound />} />
            </Routes>
          </div>
        </Router>
      </div>
    </div>
  );
};

export default App;
// Catogory1/index.jsx
import React from "react";
import {Outlet, Link} from "react-router-dom";

const Category1 = () => {
  return (
    <React.Fragment>
      <div className="flex flex-row px-5 py-2 border-b font-bold space-x-2">
        <Link to={`/category1`}>Page1</Link>
        <Link to={`/category1/page2`}>Page2</Link>
      </div>
      <div className="flex flex-row">
        Category1 {">>"}
        <Outlet />
      </div>
    </React.Fragment>
  );
};

export default Category1;
// Catogory2/index.jsx
import React from "react";
import {Outlet, Link} from "react-router-dom";

const Category2 = () => {
  return (
    <React.Fragment>
      <div className="flex flex-row px-10 py-2 border-b font-bold space-x-2">
        <Link to={`/category2/page3`}>Page3</Link>
        <Link to={`/category2/page4`}>Page4</Link>
      </div>
      <div className="flex flex-row">
        Category2 {">>"}
        <Outlet />
      </div>
    </React.Fragment>
  );
};

export default Category2;

Reference

https://blog.logrocket.com/react-router-v6-guide/

0개의 댓글

관련 채용 정보