도리쓰에러쓰

[React] React Router 1 :: 세팅과 기본 라우팅 본문

코딩애플 (React)/기초수업 (코딩애플) - 2

[React] React Router 1 :: 세팅과 기본 라우팅

강도리 2022. 1. 11. 15:51

저번 게시물에 이어서 페이지를 나누는 React Router를 작성해보겠습니다. (저번 게시물 코드 참고)

 

[React] 반복문(map())을 이용하여 컴포넌트(Component) 반복 출력하기

지난 게시물을 통해 App.js로 가져온 데이터를 이용해 컴포넌트(Component) 안에 출력시켜 보도록 하겠습니다. 2022.01.08 - [React] - [React] Export(내보내기) 및 Import(가져오기) [React] Export(내보내기)..

dori-coding.tistory.com


1. React Router란?

React Router는 하나의 페이지에서 필요한 데이터만 가져오는 형태이다. 이 말은 즉슨, 페이지마다 다른 HTML 파일이 아니라 HTML 내부를 갈아치워서 다른 페이지처럼 보여주게 하는 것이 React Router이다.
(HTML 파일은 index.html 하나뿐이다.)

2. React-router-dom 초기 세팅 방법

 * react-router-dom 라이브러리 사용

  • 터미널에 npm install react-router-dom@5 혹은 yarn add react-router-dom@5 입력하기 (yarn은 yarn 설치한 사람만)
  • index.js에 import { BrowserRouter } from 'react-router-dom'; 작성하기
  • index.js에 <App /><BrowserRouter>에 둘러싸기

index.js

import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

3. React Router의 종류

  • BrowserRouter : 라우팅을 리액트가 아니라 서버에게 요청할 수도 있어서 위험하다. (서버에서 서버 라우팅 방지하는 API를 작성해둬야한다.)
  • HashRouter : 라우팅을 안전하게 할 수 있도록 도와준다. 또, 사이트 주스 뒤에 #이 붙는데 # 뒤에 적혀있는 것은 서버로 전달되지 않는다. 그래서 라우팅을 리액트가 알아서 잘 해줄 수 있다.

4. Route 작성 방법

1. <Route path="/경로"> </Route>
2. <Route path="/경로" component={component명}> </Route> - Component를 Route 안에 넣는 코드를 깔끔하게 작성 가능하다.

5. Route 만들기 (페이지 나누기)

* App.js에 import 하기

import { Link, Route, Switch } from 'react-route-dom';

 

* <Route path="/경로"> 작성하고 태그 안에 HTML 적기

<Route path="/">
	<div>메인페이지</div>
</Route>
<Route path="/detail">
	<div>상세페이지</div>
</Route>

 


* 경로가 'localhost:포트번호'일 때의 화면

 

* 경로가 'localhost:포트번호/detail'일 때의 화면


✨ '/detail' 경로로 접속해도 '/' 경로 내용이 보이는 이유? 해결 방법?

React Router는 매칭 되는 것을 한꺼번에 다 보여주기 때문에 '/detail' 경로로 접속해도 '/' 경로 내용이 보이는 것이다. 이를 해결하기 위해서는 Route에 exact라는 속성을 추가하면 경로가 정확히 일치할 때만 보여준다.

 

* exact 속성 적용했을 때

<Route exact path="/">
	<div>메인페이지</div>
</Route>
<Route path="/detail">
	<div>상세페이지</div>
</Route>

경로가 '/detail'일 때의 화면 (exact 속성이 적용된 것을 확인할 수 있다.)


이전 게시물에 만들어놨던 화면을 '메인페이지' Route에 넣어주고, '상세페이지'엔 우선 간단한 코드를 작성해주었다. (App.js 코드 참고)

 

5. 전체 코드

App.js

/* eslint-disable */
import React, { useState } from 'react'
import { Navbar, Container, Nav, NavDropdown, Button } from 'react-bootstrap';
import './App.css';
import data from './data.js';

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

function App() {

  let [products, setProducts] = useState(data);

  return (
    <div className="App">
      <Navbar bg="light" expand="lg">
        <Container>
          <Navbar.Brand href="#home">Saint Laurent</Navbar.Brand>
          <Navbar.Toggle aria-controls="basic-navbar-nav" />
          <Navbar.Collapse id="basic-navbar-nav">
            <Nav className="me-auto">
              <Nav.Link href="#home">Home</Nav.Link>
              <Nav.Link href="#link">Link</Nav.Link>
              <NavDropdown title="Dropdown" id="basic-nav-dropdown">
                <NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
                <NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item>
                <NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
                <NavDropdown.Divider />
                <NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item>
              </NavDropdown>
            </Nav>
          </Navbar.Collapse>
        </Container>
      </Navbar>

      <Route exact path="/">
        <div className='Jumbotron'>
          <h1>20% Season Off</h1>
          <p>
            This is a simple hero unit, a simple jumbotron-style component for calling
            extra attention to featured content or information.
          </p>
          <p>
            <Button variant="primary">Learn more</Button>
          </p>
        </div>

        <div className='container'>
          <div className='row'>
            {
              products.map((a, i) => {
                return <Card products={a} num={i} key={i}/>
              })
            }
          </div>
        </div>
      </Route>
      <Route path="/detail">
        <div className='container'>
          <div className='row'>
            <div className='col-md-6'>
              <img className='img' src='images/img1.jpg' />
            </div>
            <div className='col-md-6 mt-4'>
              <h4 className='pt-5'>상품명</h4>
              <p>상품 설명</p>
              <p>1200000원</p>
              <button className='btn btn-danger'>주문하기</button>
            </div>
          </div>
        </div>
      </Route>

    </div>
  );
}

function Card(props) {
  return(
    <div className='col-md-4'>
      <img className="img" src={ 'images/img'+ (props.num + 1) +'.jpg' } />
      <h4>{ props.products.title }</h4>
      <p>{ props.products.content }</p>
      <p>{ props.products.price }</p>
    </div>
  )
}

export default App;

 

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

* App.css와 index.html은 이전 게시물의 코드와 동일하다.


* 경로가 'localhost:포트번호'일 때의 화면

 

* 경로가 'localhost:포트번호/detail'일 때의 화면

Comments