도리쓰에러쓰

[React] React Router 2 :: Link, History, Switch 기능 본문

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

[React] React Router 2 :: Link, History, Switch 기능

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

저번 게시물에 이어서 작성해보겠습니다. (저번 게시물 코드 참고)

 

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

저번 게시물에 이어서 페이지를 나누는 React Router를 작성해보겠습니다. (저번 게시물 코드 참고) 2022.01.10 - [React] - [React] 반복문(map())을 이용하여 컴포넌트(Component) 반복 출력하기 [React] 반복문..

dori-coding.tistory.com


1. '상세페이지' 화면 Component화하기 (다른 파일에 있는 Component를 App.js로 import하여 사용하기)

* src/Detail.js 파일 생성 (컴포넌트 파일은 대문자로 시작하는게 관습)

 

* Detail.js 파일 안에 Detail() 컴포넌트 만들어주고 컴포넌트를 사용하기 위해 react import 하기

import React, { useState } from 'react';

function Detail() {

    return(
        <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>
    )
}

 

* Detail.js에 있는 Detail 컴포넌트를 App.js에서 사용하기 위해 export 하기 (export default 함수명;)

export default Detail;

 

* App.js에서 import 하기

import Detail from './Detail.js'

 

* App.js의 '상세페이지' <Route>에 Component 작성하기

<Route path="/detail">
    <Detail />
</Route>

2. 'react-router-dom' 라이브러리의 <Link> Component 사용하기

* App.js에서 <Navbar> 내용 변경 및 버튼에 href 지우기

<Nav.Link>Home</Nav.Link>
<Nav.Link>Detail</Nav.Link>

 

* <Link> Component 작성하기 (이전에 'react-router-dom' 라이브러리 import 하였음.)

 📌 작성 방법 : <Link to="경로">버튼</Link>

<Nav.Link><Link to="/">Home</Link></Nav.Link>
<Nav.Link><Link to="/detail">Detail</Link></Nav.Link>

 

[Home]과 [Detail]의 Link가 생성되었다. (파란 글씨 없애고 싶으면 css 추가하기)


3. 'react-router-dom' 라이브러리의 useHistory() 사용하여 페이지 이동시키기 (<Detail> Component에 [뒤로가기] 버튼 생성)

 * Detail.js에 버튼 하나 생성해주기

<button className='btn btn-danger'>뒤로가기</button>

 

* 'react-router-dom' 라이브러리의 useHistory라는 훅 import하기

📌 사용 조건
 1. react-router-dom v5 이상
 2. react v16.3 이상
import { useHistory } from 'react-router-dom';

 

* 변수 하나 생성하여 useHistory() 훅 저장하기 (방문기록 등을 저장하는 Object)

let history = useHistory();

 

* useHistory() 훅 사용하기

<button className='btn btn-danger' onClick={ () => {
    history.goBack();
}}>뒤로가기</button>
history뒤엔 여러 속성을 작성할 수 있는데 history.goBack();은 이전 페이지로 이동하고,
history.push('경로')는 작성한 경로로 이동한다.
(이 외에도 여러 속성이 있다.)

 

[뒤로가기] 버튼을 클릭하면 이전 화면으로 이동한다.


4. 'react-router-dom' 라이브러리의 <Switch> Component 사용하기

* App.js에 새로운 <Route> 생성하기

 📌 ':' 뒤엔 Parameter 작성 (쉽게 생각하면 '/모든문자'라는 경로를 의미)

<Route path="/:id">

</Route>

 

* '/detail'로 접속해도 매칭이 되서 div 안의 내용이 보여짐.

<Route path="/:id">
  <div>아무말</div>
</Route>

경로 'localhost:포트번호/detail'의 화면인데 '아무말'이라는 태그가 보임.

 

* 여러 Route가 매치되어도 하나의 Route만 보여지고 싶다면 <Switch> Component를 사용하면 된다.

📌 Switch 안에 담았더니 Route 들이 하나씩만 보임 (중복 출연이 되지 않고, 제일 위에 것만 보여짐)

<Switch>
    <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">
      <Detail />
    </Route>

    <Route path="/:id">
        <div>아무말</div>
    </Route>
  </Switch>

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 Detail from './Detail.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><Link to="/">Home</Link></Nav.Link>
              <Nav.Link><Link to="/detail">Detail</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>

      <Switch>
        <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">
          <Detail />
        </Route>
        
        <Route path="/:id">
            <div>아무말</div>
        </Route>
      </Switch>
    </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;

 

Detail.js

import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';

function Detail() {

    let history = useHistory();

    return(
        <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>
                <br />
                <br />
                <button className='btn btn-danger' onClick={ () => {
                    history.goBack();
                }}>뒤로가기</button>
            </div>
            </div>
        </div>
    )
}

export default Detail;

 

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

Comments