ecoEarth 2023. 1. 8. 17:05

react-router-dom이란?

 

yarn add react-router-dom

 

styled-components, redux 에 이어서 또 하나의 패키지를 소개합니다. 바로 react-router-dom 입니다. 지금까지 우리가 많은 실습과 과제를 했는데, 어딘가 좀 허전하지 않으셨나요?

네이버나 또는 다른 웹사이트를 우리가 사용할 때 보통 이 페이지에도 갔다가 저 페이지에도 갔다가 여러 페이지로 오가며 이동할 수 있는데, 우리는 항상 한 페이지에 머물러 있었어요. 하지만 오늘 react-router-dom을 배우면 여러 페이지를 가진 웹을 만들 수 있게 됩니다!


react-router-dom 사용하기

  • src/pages폴더에 router에서 뿌려줄 페이지컴포넌트들 생성하기
  • src/Router.js에  router설정 코드 작성하기
  • src/App.js에 Router import및 적용
  • 정상작동 테스트

 

src/Router.js

이번 챕터에서 가장 중요한 부분이라고 할 수 있습니다. 브라우저에 우리가 URL을 입력하고 이동했을 때 우리가 원하는 페이지 컴포넌트로 이동하게끔 만드는 부분입니다. URL 1개당 페이지 컴포넌트를 매칭해주는 것이죠. 이 한개의 URL을 Route 라고 합니다.

그리고 Route들을 설정하는 코드는 Router.js 라는 파일을 별도로 분리해서 많이 작성하곤 합니다. 우리도 이 방식으로 한번 작성해보겠습니다. src안에 shared 라는 폴더를 생성해주고, 그 안에 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";

const Router = () => {
  return (
    <BrowserRouter>
        <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

Router.js를 다른 곳도 아닌 App 컴포넌트에 넣어주는 이유는 우리가 만든 프로젝트에서 가장 최상위에 존재하는 컴포넌트가 App.js 이기 때문입니다.

즉, 우리가 어떤 컴포넌트를 화면에 띄우던, 항상 App.js를 거쳐야만 합니다. 그래서 path 별로 분기가 되는 Router.js 를 App.js에 위치시키고 우리의 서비스를 이용하는 모든 사용자가 항상 App.js → Router.js 거치도록 코드를 구현해주는 것입니다.

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

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

export default App;

react-router-dom Hooks

https://reactrouter.com/en/6.6.1

 

Home v6.6.1

I'm on v5 The migration guide will help you migrate incrementally and keep shipping along the way. Or, do it all in one yolo commit! Either way, we've got you covered to start using the new features right away.

reactrouter.com

 

(1) useNavigate

다른 페이지로 보내고자 할 때 사용할 수 있습니다. 위에서 테스트 했을 때 우리가 브라우저에 직접 path를 입력해서 페이지를 이동했었죠?

근데 사실 사용자들이 브라우저에 path를 직접 입력해서 페이지를 이동하게 만드는 서비스는 거의 없을 것 입니다. 보통 어떤 버튼을 누르면 페이지로 이동하거나 또는 어떤 컴포넌트를 눌렀을 때 페이지를 이동하게 만들죠. 그럴 때 사용하는 훅 입니다.

버튼의 클릭 이벤트 핸들러에 아래와 같이 코드를 작성하면 버튼을 클릭했을 때 우리가 보내고자 하는 path로 페이지를 이동시킬 수 있습니다. 꼭 버튼이 아니더라도, 컴포넌트의 클릭 이벤트 핸들러를 통해서 활용할 수 있습니다.

 

사용방법은 아래와 같습니다.

  • navigate 를 생성한다.
  • navigate(’보내고자 하는 url’)함수를 호출시킨다. 

 

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;

 

(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;

 

(3) Link

Link 는 훅이 아니지만, 꼭 알아야 할 API라서 소개합니다.

Link 는 html 태그중에 a 태그의 기능을 대체하는 API 입니다. 만약 JSX에서 a 태그를 사용해야 한다면, 반드시 Link 를 사용해서 구현해야 합니다. 왜냐하면 a 태그를 사용하면 페이지를 이동하면서 브라우저가 새로고침(refresh)되기 때문입니다. 브라우저가 새로고침 되면   -> 모든 컴포넌트가 다시 렌더링되야 하고 -> 또한 우리가 리덕스나 useState를 통해 메모리상에 구축해놓은 모든 상태값이 초기화 됩니다. 이것은 곧 성능에 악역향을 줄 수 있고, 불필요한 움직임입니다.

페이지를 이동시키고자 할때 useNavigate 또는 Link를 사용할 수 있게 됐습니다. 앞으로 여러분이 구현을 하면서 더 적합한 방식으로 API를 활용하시면 됩니다. 사용방법은 아래 코드를 참고해주세요. 

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 용도

어떤 컴포넌트들은 어떤 자식 엘리먼트가 들어올지 미리 예상할 수 없는 경우가 있습니다.

범용적인 ‘박스’ 역할을 하는 Sidebar 혹은 Dialog와 같은 컴포넌트에서 특히 자주 볼 수 있습니다

여기서 말하는 범용적인 “박스” 역할을 하는 컴포넌트란 크게 봤을 때 Layout 역할을 하는 컴포넌트라고 생각해볼 수 있습니다. children props를 찾아보시면 composition이라는 말을 많이 보시게 될 텐데요, composition은 합성이라는 의미가 있다고 합니다.

이번 섹션에서는 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>Sparta Coding Club - Let's learn React</span>
    </div>
  );
}

function Footer() {
  return (
    <div style={{ ...FooterStyles }}>
      <span>copyright @SCC</span>
    </div>
  );
}


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

export default Layout;

 

src/shared/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 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;

최종정리

  • react-router-dom을 이용하면, SPA 기반 인 리액트 프로젝트 안에서 여러개의 페이지를 구현할 수 있다.
  • Router.js에 Route 설정에 관련된 코드를 작성하고, 최상위 컴포넌트인 App.js에서 import 해서 사용한다.
  • react-router-dom는 여러가지 훅을 제공한다