[코드잇] 리액트 라우터 - 2. 하위 페이지(index, outlet), 동적경로(useParams)

iberis2·2023년 4월 8일
0

React 리액트

목록 보기
11/20
post-thumbnail

📑 하위 페이지 나누기 : Route, index

/courses 의 하위 페이지로 /courses/react-frontend-development 등 여러 페이지가 있을 때 해당 페이지들을 따로 묶어줄 수 있다.

  1. <Route path ="courses"> </Route> 사이에 관련 페이지를 모두 넣고,
  2. 기준이 되는 페이지(<Route path="/courses" element={<CourseListPage />} />) 에서 pathindex로 바꿔준다.
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./components/App";
import CourseListPage from "./pages/CourseListPage";
import CoursePage from "./pages/CoursePage";

function Main() {
  return (
    <BrowserRouter>
      <App>
        <Routes>
          <Route path="/" element={<HomePage />} />
{/* courses 의 하위 경로를 만들고 싶을 때 Route로 다시 감싼다. */}
          <Route path="courses">
            <Route index element={<CourseListPage />} />
            <Route path="react-frontend-development" element={<CoursePage />} />
          </Route>
        </Routes>
      </App>
    </BrowserRouter>
  );
}

📑 하위 페이지에 공통된 레이아웃 지정 : Outlet

부모 Route 컴포넌트에 element 를 지정하고,
Outlet 이라는 컴포넌트를 활용하면 공통된 레이아웃을 지정해줄 수 있다.

위 코드에서 모든 컴포넌츠들은 <App> </App> 컴포넌츠 사이에 하위 컴포넌츠로 들어있다.

App 컴포넌츠에서는 하위 컴포넌츠를 { children } props로 받아 <Nav /><Footer /> 사이에 렌더링 한다.

// App.js
import Nav from "../components/Nav";
import Footer from "../components/Footer";

function App({children}) {
  return (
    <>
      <Nav />
      <div >
        {children}
      </div>
      <Footer />
    </>
  );
}

{children} props로 전달되는 하위 컴포넌츠들을 <Outlet /> 컴포넌츠로 바꾸면 App 컴포넌츠의 레이아웃(네비 - 컴포넌츠 - 푸터)을
하위 컴포넌츠들에 공통적으로 지정해줄 수 있다.

  1. <App> 컴포넌츠를 바로 <Routes> 안에 넣으면 오류가 난다.
    • <Route element={<App />}> 로 감싸주고 모든 하위 경로를 나타낼 것이므로 path="/" 를 추가해준다.
  2. 최상위 경로에 해당하는 경로는 path prop이 아니라
    index 라는 prop을 사용하므로, <Homepage> 컴포넌츠의 pathindex로 바꿔준다.
// main.js 
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./components/App";
import HomePage from "./pages/HomePage";
import CourseListPage from "./pages/CourseListPage";
import CoursePage from "./pages/CoursePage";

function Main() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<App />}>
          <Route index element={<HomePage />} />
          <Route path="courses">
            <Route index element={<CourseListPage />} />
            <Route path="react-frontend-development" element={<CoursePage />} />
          </Route>
        </Route>
      </Routes>
    </BrowserRouter>
  );
}
  1. App 컴포넌츠에서 {children} 으로 받았던 하위 컴포넌츠들을 삭제한다.
  2. Outlet을 import 해서 children 대신 <Outlet>을 사용한다.
import { Outlet } from "react-router-dom";

function App() {
  return (
    <>
      <Nav className={styles.nav} />
      <div className={styles.body}>
        <Outlet />
      </div>
      <Footer className={styles.footer} />
    </>
  );
}

📑 동적 경로 만들기 : useParams

파라미터(parameter): 경로에서 사용하는 동적인 값
params : 파라미터들을 모아놓은 것

URL에서 /courses의 하위 경로로 /courses/react, /courses/javascript, ... 등 여러 개의 파라미터가 있을 수 있다.
동적으로 변하는 parameter 경로들에 대해 보여줄 모든 페이지들을<Route path="">로 하드 코딩하는 것은 매우 번거로운 일이다.

따라서 경로를 고정적인 값이 아닌 달라지는 동적 경로(parameter)로 정해줄 때 :를 앞에 붙이고 이름을 지정해준다.

  • 참고로 slug 는 URL의 한 부분으로 사람이 읽기 쉬운 키워드로 페이지를 구분하게 해주는 키워드를 뜻한다.
// main.js

// 바꾸기 전
// courses 경로(path)의 모든 하위 경로(parameter)에 보여줄 컴포넌츠만 지정되어 있다.
<Route path="courses">
  <Route index element={<CourseListPage />} />
  <Route path="react-frontend-development" element={<CoursePage />} />
  <Route path="javascript-intermediate" element={<CoursePage />} />
  // parameter의 수만큼 반복해야함 
</Route>

// 바꾼 후
// courses 경로(path) 의 하위 경로(parameter)로 여러 courseSlug 값들이 올 수 있다.
<Route path=":courseSlug" element={<CoursePage />} />

useParams() 는 현재 URL에서 <Route path="경로">와 일치하는 key/value 가 들어있는 객체를 반환한다.
🔗 ReactRouter 공식홈페이지 : useParams

❊ 참고로 parameter가 아닌 현재 페이지의 pathname을 가져오려면 useLocation()을 사용해야 한다.

useParams 가 리턴하는 객체에는 현재 경로의 parameter 가 저장되어 있다.

<Route />에서 동적 경로로 지정한 경로는 페이지 경로가 달라질 때마다 useParams()에서 리턴하는 파라미터 값도 달라진다.
따라서 하나의 컴포넌츠(CoursePage.js)를 가지고 parameter에 따라 달라진 데이터를 받아서 서로 다른 페이지처럼 보여줄 수 있다.

// CoursePage.js
import { useParams } from "react-router-dom";

function CoursePage() {
  const { courseSlug } = useParams(); // 현재 경로(파라미터들)를 객체로 리턴
  // 현재 URL의 파라미터(경로)가 { courseSlug: "경로"}로 리턴된다.
  
  {/* 바꾸기 전 :
  const course = getCourseBySlug('react-frontend-development'); 
  하나의 경로에서만 course 객체가 리턴되었음*/}
 
  const course = getCourseBySlug(courseSlug); // courseSlug 값에 따라 course 데이터 객체를 리턴 함수
  const courseColor = getCourseColor(course?.code);

 {/* 하기 내용 함수 생략 */}

  return (
    <>
       {/* 데이터 course.title, course.content 로 화면 구성 */}
    </>
  );
}
profile
React, Next.js, TypeScript 로 개발 중인 프론트엔드 개발자

0개의 댓글