[React] react-router-dom

 패키지 설치

yarn add react-router-dom

 

사용 순서

페이지 컴포넌트 생성

pages 폴더 내에 .jsx 파일들 생성해줌

  • Home.jsx
  • About.jsx
  • Works.jsx
  • Contact.jsx

scr > shared 폴더에 Router.jsx 파일 생성

const { BrowserRouter } = require("react-router-dom");

const Router = () => {
  return <BrowserRouter></BrowserRouter>;
};

export default Router;

BrowserRouter > Routes > 여러 Route들 의 계층구조로 만든다

- 이 Route 들을 이동할 수 있는 SPA를 만드는 것! 

 

Route는 두개의 props를 받는다

  • path: 프로젝트에서 사용할 경로
  • element: 표시할 컴포넌트
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "../pages/Home";
import About from "../pages/About";
import Contact from "../pages/Contact";
import Works from "../pages/Works";

const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
        <Route path="/works" element={<Works />} />
      </Routes>
    </BrowserRouter>
  );
};

export default Router;

 

 

App.js에 import 및 적용

Router.jsx에서 Router import! react-router-dom의 Router import 하지 않도록 주의

import Router from "./shared/Router";

function App() {
  return (
    <>
      <Router />
    </>
  );
}

export default App;

 

페이지 이동 확인

실행시켜보면 기본경로에서 Home, 기본경로/about에서 About 등 경로에 맞는 컴포넌트가 보이는 것을 확인할 수 있다!

 

 

 

react-router-dom hooks

useNavigate

특정 페이지로의 이동을 구현하는 훅

import { useNavigate } from "react-router-dom";

const Home = () => {
  const navigate = useNavigate();

  return (
    <div>
      <div>Home</div>
      <button onClick={() => navigate("/works")}>Works로 이동</button>
    </div>
  );
};

export default Home;

 

 

useLocation

react-router-dom을 사용하면 현재 위치하고 있는 페이지의 여러가지 정보를 추가적으로 얻을 수 있음

이 정보들을 이용해 페이지 안에서 조건부 렌더링을 활용할 수 있음

import { useNavigate, useLocation } from "react-router-dom";

const Works = () => {
  const location = useLocation();
  console.log(location);
};

useLocation으로 받아온 location을 console.log로 출력해보면 아래와같이 객체 형태로 값이 저장돼있음을 확인할 수 있다

따라서 location.pathname.slice(1) 등으로 경로 정보를 활용할 수 있다

 

 

Link 태그

.jsx에서 a태그를 사용하고 싶은 경우 Link 태그를 사용한다.

(a태그는 새로고침하며 이동 -> SPA 아님)

import Link from 'react-router-dom';

<Link to="/contact">Contact 페이지로 이동하기</Link>

 

 

children 활용해 레이아웃 만들기

router 기능으로 다른 path들로 이동하면서, 공통적으로 필요한 layout이 있을 수 있다.

1. Routes 전체를 감싸는 Layout 컴포넌트 생성

2. Layout 컴포넌트는 children을 받아 내부 요소를 구성함

function Layout({children}) {
  return (
    <div>
      <Header/>
      <div style={{...layoutStyles}}>{children}</div>
      <Footer/>
    </div>
  )
}

이렇게하면 틀 안에서 보여지는 컴포넌트들을 바꿔가며 사용할 수 있다!

 

 

Dynamic routing (동적 라우팅)

path에 유동적인 값을 넣어서 특정 페이지로 이동하게 하는 것

 

방법

<Route/>의 path에 :속성을 넣어준다

<Route path="works/:id" elements={<Works/>} />

그럼 기본적으로 Works 컴포넌트지만 id에 따라 다른 값을 보여주도록 활용할 수 있다!

 

const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
        <Route path="/works" element={<Works />} />
        <Route path="/works/:id" element={<Works />} />
      </Routes>
    </BrowserRouter>
  );
};
const Works = () => {
  const data = [
    { id: 1, todo: "리액트 배우기" },
    { id: 2, todo: "운동하기" },
    { id: 3, todo: "또띠아 해먹기" },
  ];

  return (
    <div>
      <div>Works</div>
      {data.map((work) => {
        return (
          <div key={work.id}>
            <div>할 일: {work.id}</div>
            <Link to={`/works/${work.id}`}>"{work.todo}"로 이동</Link>
          </div>
        );
      })}
    </div>
  );
};

export default Works;

 

useParams hook

동적 라우팅으로 전달받은 다른 속성값을 변수로 받아 활용할 수 있다.

useParams()로 반환받은 객체는 동적라우팅으로 전달받은 값을 갖고있다

key가 id인 이유는 동적라우팅에서 지정한 값이 :id였기 때문!

 

const Works = () => {
  const param = useParams();

  const data = [
    { id: 1, todo: "리액트 배우기" },
    { id: 2, todo: "운동하기" },
    { id: 3, todo: "또띠아 해먹기" },
  ];

  const targetWork = data.find((work) => work.id === Number(param.id));
  
  // 생략
  }

이와같이 활용해 works 컴포넌트 중에서도 어떤 추가적인 패스를 전달받아 왔는지, 그리고 그 정보를 활용해 필요한 값을 얻을 수 있다

param으로 받는 값은 문자열이기 때문에 비교할 때 경우에따라 형변환이 필요할 수 있다.

 

return (
  <div>
    <div>Works</div>
    <div>현재 페이지는 {targetWork.todo}입니다.</div>
    // 생략
  </div>
)

 

 

중첩된 라우트 Oulet

중첩 라우팅

특정 라우트 내에서 추가적인 라우트를 정의하는 방식

웹 애플리케이션에서 여러 계층의 UI를 구성할 때 유용하게 사용됨

예를들어, 사용자 대시보드에 여러 섹션이 있는 경우 섹션 별로 다른 경로를 설정할 수 있음

 

예제

1. DashBoardLayout.jsx 생성

function DashBoardLayout() {
  return <div>DashBoardLayout</div>;
}

export default DashBoardLayout;

 

2. Route 지정

const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
        <Route path="/works" element={<Works />} />
        <Route path="/works/:id" element={<Works />} />
        <Route path="/dashboard" element={<DashBoardLayout />} />
      </Routes>
    </BrowserRouter>
  );
};

 

이 dashboard 아래로 마이페이지도 있고, 좋아요한 목록도 있고 다양하게 존재했으면 좋겠음

 

3. MyPage 컴포넌트 생성하고 dashboard Route의 children으로 Route 생성

<Route path="/dashboard" element={<DashBoardLayout />}>
  <Route path="mypage" element={<MyPage />} />
</Route>

 

4. outlet 사용

지금 단계까지의 상태에서 /dashboard/mypage로 들어가면 대시보드 컴포넌트 내용만 보인다.

이를 해결하기 위해 outlet이 필요함 (DashBoardLayout에서 사용)

 

import { Outlet } from "react-router-dom";

function DashBoardLayout() {
  return (
    <div>
      <h1>DashBoardLayout</h1>
      <Outlet />
    </div>
  );
}

export default DashBoardLayout;

 

대시보드에 또다른 중첩된 path가 추가된다면?

이동한 경로에따라 해당하는 하위 경로의 컴포넌트를 보여준다

 

Layout과의 차이?

레이아웃은 무조건 전체적인 스타일을 지정할 때 사용 가능함

DashBoard의 아래에 다양한 케이스를 추가하고 싶은 경우에는 outlet을 활용하는 것이 더 적합