천진난만 코딩 스토리

2023.03.04) 항해 27일차 (2-React Router Dom) 본문

TIL(Today I Learned)

2023.03.04) 항해 27일차 (2-React Router Dom)

Wisdom_1104 2023. 3. 4. 23:00

라우터 돔은 생각보단 괜찮았는데 손에 익지는 않아서

내일 리덕스와 함께 해봐야겠다는 생각을 했다.

일요일이지만 쉴 수 없다.......

이해 못한 나를 탓해야지...어쩔 수 없지!!!!

 

1) react-router-dom

페이지를 구현할 수 있게 해주는 패키지이다.

//아래의 명령어로 설치한다
yarn add react-router-dom
  1. react-redux처럼 react-router-dom도 폴더를 생성해 주어야 한다.
  2. pages폴더 생성 -> 안에 필요한 여러 페이지 생성 ex) Home.jsx , About.jsx ...
  3. shared 폴더 생성 -> 안에 Router.js 생성 -> router 설정 코드 작성
  4. App.js 에서 import도 해야한다.
  5.  

Routes안에 있는 Route에는 react-router-dom에서 지원하는 props들이 있다.

path원하는 "주소"를 넣어준다.
element해당 주소로 이동했을 때 보여주고자 하는 page 컴포넌트를 작성한다.

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

Router.js 파일을 App.js에 import 해주어야 한다.

Router.js를 다른 곳도 아닌 App 컴포넌트에 넣어주는 이유는,

우리가 만든 프로젝트에서 가장 최상위에 존재하는 컴포넌트가 App.js 이기 때문이다.

즉 ,우리가 어떤 컴포넌트를 화면에 띄우던 항상 App.js를 거쳐야만 한다.

그래서 path 별로 분기가 되는 Router.js 를 App.js에 위치시키고,

우리의 서비스를 이용하는 모든 사용자가 항상 App.js → Router.js 거치도록 코드를 구현해주는 것이다.

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

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

export default App;

 

 

2) react-router-dom Hooks

① useNavigate

버튼의 클릭 이벤트 핸들러에 코드를 작성하면 버튼을 클릭했을 때 우리가 보내고자 하는 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;

② Link

페이지를 이동시키고자 할때 useNavigate 또는 Link를 사용할 수 있다.

Link 는 훅이 아니지만, 꼭 알아야 할 API이다.

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

만약 JSX에서 a 태그를 사용해야 한다면, 반드시 Link 를 사용해서 구현해야 한다.

  • a태그 말고 Link를 사용해야 하는 이유
  • a 태그를 사용하면 페이지를 이동하면서 브라우저가 새로고침(refresh)된다.
  • 브라우저가 새로고침 되면 모든 컴포넌트가 다시 렌더링되야 하고,
  • 리덕스나 useState를 통해 메모리상에 구축해놓은 모든 상태값이 초기화 된다.
  • 이것은 곧 성능에 악역향을 줄 수 있고, 불필요한 움직임이다.
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;

 

3) Dynamic route 기법과 useParam hook

① Dynamic Route란?

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

react-router-dom에서 지원하는 Dynamic Routes 기능을 이용해서 간결하게 동적으로 변하는 페이지를 처리할 수 있다.

 

 

Works 페이지에 여러개의 Work가 있고, 그것을 클릭했을 때 각각의 상세페이지로 이동하게끔 구현해봅시다. 일단 Work 라는 페이지가 먼저 있어야겠죠? Work 컴포넌트를 추가해주세요.

// src/pages/Works.js

import React from "react";

const Works = () => {
  return <div>Works</div>;
};

export default Work;

 

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

const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="works/:id" element={<Works />} /> //추가한 코드
      </Routes>
    </BrowserRouter>
  );
};

export default Router;

이전과는 다르게 path에 works/:id 라고 path가 들어갑니다. :id 라는 것이 바로 동적인 값을 받겠다라는 의미입니다.

그래서 works/1 로 이동해도 <Work /> 로 이동하고, works/2, works/3 …. works/100 모두 <Work /> 로 이동하게 해줍니다.

그리고 :id 는 useParams 훅에서 조회할 수 있는 값이 됩니다. 

 

 

② useParams

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

우리가 설정한 예제 코드에서도 Work 페이지 컴포넌트를 모두 동일하게 렌더링하겠죠?

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

아래 코드를 추가해볼까요? useParams이라는 훅을 사용해봅시다.

useParams 은 path의 있는 id 값을 조회할 수 있게 해주는 훅 입니다.

그래서 만약에 우리가 works/1로 이동하면 1 이라는 값을 주고, works/100으로 이동하면 100 이라는 값을 사용할 수 있게 해줍니다.

 

// 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: '자바스크립트 배우기' },
];

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

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

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

export default Work;

useParams 훅을 이용해서 불러온 parameter를 가져온다.
Router.js에서 설정한 Workd/:id에서 id로 parameter를 설정해놨기 때문에 하위페이지로 넘어왔을때,

이게 무슨 페이지인지 useParams를 이용해서 확인할 수 있게 된 것이다.