본문 바로가기

React

React: Router DOM - 1

01. react-router-dom

리액트 프로젝트에서 라우팅을 가능하게 하는 라이브러리

일반 웹 사이트 처럼 여러 페이지를 가진 웹은 라우팅이 필요

react-router-dom을 이용하면 여러 페이지를 가진 웹 제작 가능

02. 패키지 설치 및 사용

패키지 설치

터미널

yarn add react-router-dom

 

사용방법 순서

  1. 페이지 컴포넌트 생성
  2. Router.jsx 생성 및 router 설정 코드 작성
  3. App.jsx에 import 및 적용
  4. 페이지 이동 테스트

 

페이지 컴포넌트 생성

src 폴더 내에 하위 폴더 pages 생성

pages 폴더 내에 Home, About, Contact, Works 컴포넌트 생성

 

Router.jsx 생성 및 router 설정 코드 작성

src 폴더 내에 하위 폴더 shared 생성

shared 폴더 내에 Router.jsx 파일 생성

Router.jsx

import React from 'react'
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 = () => {
    // Route에는 2개의 인자 path, element
    // path는 localhost:5173/ 뒤에 붙는 경로
    // element는 해당 경로로 갔을 때 나올 컴포넌트
    return (
        <BrowserRouter>
            <Routes>
                {/* Route */}
                <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.jsx에 improt 및 적용

import React from 'react'
import Router from './shared/Router'

// App 컴포넌트는 가장 최상위 컴포넌트라서 여기에 Router를 import
// 항상 App 컴포넌트를 거쳐가야만 함
// path 별로 분기가 되는 Router.jsx를 App.jsx에 위치
// App.jsx -> Router.jsx를 거치도록 구현
const App = () => {
  return (
    <Router /> // Router를 가져올 때는 만들었던(shraed 폴더에 있는) Router를 가져와야함
  )
}

export default App

 

페이지 이동 테스트

경로에 아무것도 없을시 Home 컴포넌트

 

경로에 /about을 추가하면 About 컴포넌트

4개의 컴포넌트로 이동이 잘 되는 것을 확인

03. react-router-dom hooks

react-router-dom에서도 hook 제공

가장 많이 쓰이는 것들

useNavigate

A 페이지 => B 페이지로 이동하기 위한 훅

위에서는 주소를 직접 입력해서 페이지를 이동했지만 

useNavigate를 이용하면 버튼, 내비바 등의 컴포넌트를 클릭하면 이동하도록 해주는 훅

 

Home => Works 페이지로 이동하는 버튼 생성

Home.jsx

import React from 'react'
import { useNavigate } from 'react-router-dom'

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

    return (
        <div>
            <h1>Home 컴포넌트 입니다.</h1>
            <button onClick={() => {
                navigate("/works") // 원하는 경로를 인자로 넣어줌
            }}>
                Works로 이동
            </button>
        </div>
    )
}

export default Home

 

 

useLocation 

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

이 정보들로 페이지 안에서 조건부 렌더링 등에 사용가능, 활용성 높음

Works.jsx

import React from 'react'
import { useLocation, useNavigate } from 'react-router-dom'

const Works = () => {
    const navigate = useNavigate();
    const location = useLocation();

    console.log(location);

    return (
        <div>
            <h1>Works 컴포넌트 입니다.</h1>
            <div>
                현재 페이지 : {location.pathname.slice(1)}
            </div>
            <button onClick={() => {
                navigate("/")
            }}>Home으로 이동</button>
        </div>
    )
}

export default Works

 

Link

훅은 아니지만 HTML의 a태그처럼 쓰이는 react-router-dom의 API

React에서는 링크를 달아줄 때 a태그가 아닌 Link태그를 달아줘야함

a태그를 달면 페이지가 이동하면서 브라우저가 새로고침이 되어버림

=> 모든 컴포넌트가 다시 렌더링되야하고, Redux나 useState를 통해 메모리상에 구축해놓은 모든 상태값 초기화

 

Works.jsx

return (
        <div>
            <h1>Works 컴포넌트 입니다.</h1>
            <div>
                현재 페이지 : {location.pathname.slice(1)}
            </div>
            {/* <button onClick={() => {
                navigate("/")
            }}>Home으로 이동</button> */}
            <Link to={"/contact"}>Contact 페이지로 이동하기</Link>
        </div>
    )

브라우저 개발자도구에서 요소를 살펴보면 a태그라고 나옴

 

04. children

어떤 컴포넌트들은 어떤 자식 element가 들어올지 예상 불가한 경우가 있음

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

 

children props를 이용해 페이지 레이아웃을 만들고 개별적으로 존재하는 헤더, 푸터, 페이지를 합성해서

개발자가 의도하는 UI를 만들어주는 Layout 컴포넌트 생성해보기

Layout.jsx

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} {/* children에 Layout으로 감싼 Router들이 들어감 */}
            </div>
            <Footer />
        </div>
    );
}

export default Layout;

 

Router.jsx

return (
        <BrowserRouter>
            <Layout>
                <Routes>
                    {/* Route */}
                    <Route path='/' element={<Home />} />
                    <Route path='/about' element={<About />} />
                    <Route path='/contact' element={<Contact />} />
                    <Route path='/works' element={<Works />} />
                </Routes>
            </Layout>
        </BrowserRouter>
    )