[React] react-router-dom

·2023년 12월 20일
1

React

목록 보기
6/7
post-thumbnail

📌react-router-dom 이란?

: 페이지를 구현할 수 있게 해주는 패키지
→ SPA (single Page Application)기반인 React 프로젝트 안에서 여러 개의 페이지를 구현할 수 있다.

📌react-router-dom 설치하기

: 패키지 설치
yarn add react-router-dom
react-router-dom 설치


📌react-router-dom 사용하기

0. 순서

  • 페이지 컴포넌트 생성
  • Router.js 생성 및 router 설정 코드 작성
  • App.js에 import 및 적용

1. 페이지 컴포넌트 생성 (예시)

src폴더에 pages 폴더를 만들고 Home About Contact Works 4개의 컴포넌트 생성


2. Router.js 생성 및 router 설정 코드 작성

: 브라우저에 url을 입력하고 이동했을 때 우리가 원하는 페이지 컴포넌트로 이동하게 만드는 부분
: url 하나당 1개의 페이지 컴포넌트 매칭 → URL = Route
: 일반적으로 Route 설정 코드는 Router.js 라는 파일을 별도로 분리해서 작성한다.

(1) src 폴더 안에 shared 폴더를 생성하고 그 안에 Router.js 파일 생성

import React from "react";
//react-router-dom을 사용하기 위해 API import
import { BrowserRouter, Route, Routes } from "react-router-dom";

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

export default Router;

<BrowserRouter><Router>로 감싸는 이유는 브라우저가 깜빡이지 않고 다른 페이지로 이동할 수 있게 만들어주기 위함!! (SPA의 장점)

Route를 설정할 뼈대 완성!!


(2) 페이지 컴포넌트 마다 Route 설정하기

Router.js

import React from "react";
//react-router-dom을 사용하기 위해 API import
import { BrowserRouter, Route, Routes } 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;

<Route/>에는 react-router-dom에서 지원하는 props가 있어서
path는 우리가 사용하고 싶은 주소를 넣어주고
element는 해당 주소로 이동했을 때 보여주고자 하는 컴포넌트를 넣어주면 된다.


3. App.js에 Router.js import 하기

App.js

import React from "react";
import Router from "./shared/Router";

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

export default App;

Router.js를 App 컴포넌트에 넣는 이유는 가장 최상위 컴포넌트가 App.js이기 때문이다.

어떤 컴포넌트를 화면에 띄우던지 항상 App.js를 거쳐야하므로 path별로 분기되는 Router.jsApp.js에 위치시켜 서비스를 이용하는 모든 사용자가 항상 App.js → Router.js를 거치도록 코드를 구현하는 것이다.



📌react-router-dom Hooks

: react-router-dom에서 제공하는 다양한 hook들 (공식문서)

(1) useNavigate

: 어떤 버튼이나 컴포넌트를 눌렀을 때 페이지를 이동하도록 하는 훅

  // src/pages/home.js
import { useNavigate } from "react-router-dom";

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

  return (
    <button
      onClick={() => {
        navigate(`/works`);
      }}
    >
      works로 이동
    </button>
  );
};

export default Home;

navigate를 생성하고 navigate(이동하려는 url문자열)을 통해 페이지 이동

(2) useLocation

react-router-dom을 사용하면 현재 페이지의 정보들을 추가적으로 얻을 수 있다.

// src/pages/works.js
import { useLocation } from "react-router-dom";

const Works = () => {
  const location = useLocation();
  console.log("location :>> ", location);
  return (
    <div>
      <div>{`현재 페이지 : ${location.pathname.slice(1)}`}</div>
    </div>
  );
};

export default Works;



: Link는 html 태그 중 a태그의 기능을 대체하는 API이다.

JSX에서 a태그를 사용하면 페이지를 이동하면서 브라우저가 새로고침(refresh)되고, 브라우저가 새로고침되면 모든 컴포넌트가 다시 렌더링되어야 하고 reduxuseState를 통해 메모리상에 구축해놓은 모든 상태값이 초기화 된다.
→ 성능에 악영향줄 수 있는 불필요한 움직임이다

import { Link, useLocation } from 'react-router-dom';

const Works = () => {
  const location = useLocation();
  console.log('location :>> ', location);
  return (
    <div>
      <div>{`현재 페이지 : ${location.pathname.slice(1)}`}</div>
      <Link to="/contact">contact 페이지로 이동하기</Link>
    </div>
  );
};

export default Works;



📌children 용도

공식문서에서 설명하는 props.children

💡 어떤 컴포넌트들은 어떤 자식 엘리먼트가 들어올지 미리 예상할 수 없는 경우가 있습니다. 범용적인 ‘박스’ 역할을 하는 Sidebar 혹은 Dialog와 같은 컴포넌트에서 특히 자주 볼 수 있습니다

범용적인 ‘박스’ 역할을 하는 컴포넌트는 크게 봤을 때 Layout 역할을 하는 컴포넌트라고 생각할 수 있다.

children props를 이용해 페이지 레이아웃을 만들고 개별적으로 존재하는 Header, Footer, Page를 합성해 개발자가 의도하는 UI를 만들어주는 Layout 컴포넌트를 만들어보자.

src/shared폴더에 Layout.js파일 생성

  // src/shared/Layout.js

import React from 'react';

const HeaderStyles = {
  width: '100%',
  background: 'black',
  height: '50px',
  display: 'flex',
  alignItems: 'center',
  paddingLeft: '20px',
  color: 'white',
  fontWeight: '600',
};
const FooterStyles = {
  width: '100%',
  height: '50px',
  display: 'flex',
  background: 'black',
  color: 'white',
  alignItems: 'center',
  justifyContent: 'center',
  fontSize: '12px',
};

const layoutStyles = {
  display: 'flex',
	flexDirection: 'column',
  justifyContent: 'center',
  alignItems: 'center',
  minHeight: '90vh',
}

function Header() {
  return (
    <div style={{ ...HeaderStyles }}>
      <span>Let's learn React</span>
    </div>
  );
}

function Footer() {
  return (
    <div style={{ ...FooterStyles }}>
      <span>Have a Nice Day!</span>
    </div>
  );
}


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

export default Layout;

Router.js 수정 (<Routes> 컴포넌트를 <Layout> 컴포넌트로 감싸준다)

import React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Home from '../pages/Home';
import About from '../pages/About';
import Contact from '../pages/Contact';
import Works from '../pages/Works';
import Layout from './Layout';

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

export default Router;



📌Dynamic Routes

: 동적 라우팅. path에 유동적인 값을 넣어서 특정 페이지로 이동하게끔 하는 방법을 말한다.

예를 들어 works 페이지에 여러 개의 work가 보이고 work마다 독립적인 페이지를 갖도록 구현한다면?!

Router.js에서 Dynamic Routes를 설정한다.

import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "../pages/Home";
import About from "../pages/About";
import Contact from "../pages/Contact";
import Works from "../pages/Works";
import Layout from "./Layout";

const Router = () => {
  return (
    <BrowserRouter>
      <Layout>
        <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 />} />	//Dynamic Route
        </Routes>
      </Layout>
    </BrowserRouter>
  );
};

export default Router;

이전과는 다르게 works/:id 라고 path가 들어갑니다. :id는 동적인 값을 받겠다라는 의미이고 works/1 로 이동해도 로 이동하고, works/2, works/3 …. works/100 모두 로 이동하게 해준다.

:iduseParams 훅에서 조회할 수 있는 값이 된다.



📌useParamㄴ

: Dynamic Routes를 사용하면 element에 설정된 같은 컴포넌트를 렌더링 하게 된다.

<Route path="works/:id" element={<Work />} />

useParams을 이용하면 같은 컴포넌트를 렌더링 하더라도 각각의 고유한 id값을 조회할 수 있다.

  • Works.js 수정
  // src/pages/Works.js

import React from 'react';
import { Link } from 'react-router-dom';

const data = [
  { id: 1, todo: '리액트 배우기' },
  { id: 2, todo: '노드 배우기' },
  { id: 3, todo: '자바스크립트 배우기' },
  { id: 4, todo: '파이어 베이스 배우기' },
  { id: 5, todo: '넥스트 배우기' },
  { id: 6, todo: 'HTTP 프로토콜 배우기' },
];

function Works() {
  return (
    <div>
      {data.map((work) => {
        return (
          <div key={work.id}>
            <div>할일: {work.id}</div>
            <Link to={`/works/${work.id}`}>
              <span style={{ cursor: 'pointer' }}>➡️ Go to: {work.todo}</span>
            </Link>
          </div>
        );
      })}
    </div>
  );
}

export default Works;
  • <Work> 컴포넌트 생성
// src/pages/Work.js

import React from 'react';
import { useParams } from 'react-router-dom';

const data = [
  { id: 1, todo: '리액트 배우기' },
  { id: 2, todo: '노드 배우기' },
  { id: 3, todo: '자바스크립트 배우기' },
  { id: 4, todo: '파이어 베이스 배우기' },
  { id: 5, todo: '넥스트 배우기' },
  { id: 6, todo: 'HTTP 프로토콜 배우기' },
];

function Work() {
  const param = useParams();

  const work = data.find((work) => work.id === parseInt(param.id));

  return <div>{work.todo}</div>;
}

export default Work;
  • Router.js 수정
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "../pages/Home";
import About from "../pages/About";
import Contact from "../pages/Contact";
import Works from "../pages/Works";
import Work from "../pages/Work";
import Layout from "./Layout";

const Router = () => {
  return (
    <BrowserRouter>
      <Layout>
        <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={<Work />} />
        </Routes>
      </Layout>
    </BrowserRouter>
  );
};

export default Router;

0개의 댓글