본문 바로가기
React

React Router

by flykimjiwon 2022. 1. 13.
반응형

이와같은 창에서 각 상품별로 상세페이지를 이동할때 라우팅을 사용하면 매우좋다.

 

부드럽게 작동하기도하고 별도의 페이지를 만들기보다 컴포넌트 형태로 이동할 수 있다.

 

리액트 라우터를 사용하려면 설치부터해야한다!

 

npm install react-router-dom@5
yarn add react-router-dom@5

둘중 하나 사용해주면된다, 구글 검색하면서 세팅하도록하자

 

그리고 index.js에서 아래와같이 세팅해줘야함

import { BrowserRouter } from 'react-router-dom'
// 이거 하나를 불러와 줘야한다. /같은 경로없이 불러오는건 라이브러리다.
// import { HashRouter } from 'react-router-dom'
// 이와같이해도된다. 이건 주소에 #기호가 붙는다. 똑같지만 차이는 라우팅을 안전하게 할 수 있게도와준다.
// #이붙는거는 서버로 전달하지않는다 #은 서버에서 설정이 필요할 수 있다.

이와같이 BrowserRouter를 불러오는걸 알고있자, 해쉬 라우터를 불러와도되지만 조금의 차이가 있다.

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
    <App />
    </BrowserRouter>
    {/* 이렇게 감싸주면 설정은 끝이다. */}
    
  </React.StrictMode>,
  document.getElementById('root')
);

그리고 이와같이 기존의 <App/>컴포넌트를  감싸주면 작동시킬 수 있다.

 

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

그리고 app.js에서 이와같이 3개를 import해올건데 각각 기능을 알아보자

 

우선 원하는곳에 라우팅하려면

<Route></Route>

이와같이 불러와서 사용하면된다. 그리고 이안에 path를 적어주면된다

<Route path="/"></Route>
<Route path="/detail"></Route>
<Route path="/작명" component={Card} ></Route> 
<Route path="/작명"> <Card/> </Route>

그리고 이렇게 다 작성이가능함 안에 컴포넌트를 넣을 수 있다.

 

이런식으로하면 컴포넌트를 다른페이지를 보여주는것처럼 나타낼 수 있다. 작동도 부드럽게된다.

 

그리고 이런식으로 만들면 /가 포함된 모든페이지가 다 보이게 되는데 이런경우는

 

exact를 사용해주면된다.

<Route exact path="/"> 

</Route>

이와같이하면 / 가 있는 페이지만 보여준다.

 


Link,Switch,history

 

참고로 이전에 데이터를 import,export한것처럼 컴포넌트도 import,export해올 수 있다.

 

import React,{useState} from 'react';
import { useHistory,useParams } from 'react-router-dom/cjs/react-router-dom.min';
// 컴포넌트 만들때 꼭 import해오기

function Detail(props){
  let{ id } = useParams();
  // 파라미터값 변수로 저장해서 쓸 수 있다. 여러개가있으면 id,id2,id3..이런식으로 넣어주면댐
  let history = useHistory();
  // react-router-dom 여기들어있다. 훅입니다.
  // 방문기록등을 저장해놓는 object

  //이곳에다가 shoes데이터 Usetate해서 넣어도되지만 app에 넣는게 정석이다.
  //상위->하위컴포넌트로 쓰는게 정석 반대는 어렵기 때문

  let 찾은상품 = props.shoes.find(function(상품){
    return 상품.id==id
  })
  // return오른쪽엔 조건식이가능 이게 참이면 상품 즉 array의 하나가 찾은상품 값으로 들어감
  return(
    <div className="container">
      <div className="row">
        <div className="col-md-6">
          <img src={"https://codingapple1.github.io/shop/shoes"+(찾은상품.id+1)+".jpg"} width="100%" />
        </div>
        <div className="col-md-6 mt-4">
        <h4 className="pt-5">{찾은상품.title}</h4>
          <p>{찾은상품.content}</p>
          <p>{찾은상품.price}</p>
          {/* <h4 className="pt-5">{props.shoes[id].title}</h4>
          <p>{props.shoes[id].content}</p>
          <p>{props.shoes[id].price}</p> */}
          <button className="btn btn-danger">주문하기</button> 
          <button className="btn btn-danger" onClick={()=>{
           // history.goBack() // 뒤로 이동시키기
            history.push('/')//특정 경로로 이동시키기
            // 이런건 검색해서 사용하면된다.
           }}>뒤로가기</button> 
        </div>
      </div>
</div> 
  )
}

export default Detail;
// 변수명 or 함수명 적어주기

이와같이 컴포넌트 전체를 넣어주고 import react와 맨아래 export해주면 컴포넌트역시 다른 파일로 넣을 수 있다.

import Detail from './Detail.js'

...

    <Detail></Detail>

이렇게 불러와 바로 컴포넌트처럼 사용 할 수 있다. 마찬가지로 props까지 전부 사용가능하다.

 

- Link

Link to 를 이용해 경로를 이동할 수 있게 만들어줄 수 있다.

 <Navbar bg="light" variant="light">
    <Container>
    <Navbar.Brand href="#home">SHOP</Navbar.Brand>
    <Nav className="me-auto">
      {/* 라우터 라이브러리문법, 링크 Link불러왔음  <Link to="/">Home</Link>*/}
      <Nav.Link ><Link to="/">Home</Link></Nav.Link>
      <Nav.Link ><Link to="/detail">Detail</Link></Nav.Link>
      <Nav.Link href="#pricing">Pricing</Nav.Link>
    </Nav>
    </Container>
  </Navbar>

Navbar 안에 a태그 링크부분을 Link to 로 바꾼모습이다.

 

이것과 별개로 뒤로가기느 특정페이지에서 특정페이지로 이동하게 하려면

 

useHistory를 사용할 수 있다.

<Nav.Link as={Link} to="/"> Home </Nav.Link>

참고로 이런식으로바꿔주면 오류없이 사용할 수 있다.

-history

import React,{useState} from 'react';
import { useHistory,useParams } from 'react-router-dom/cjs/react-router-dom.min';
// 컴포넌트 만들때 꼭 import해오기


function Detail(props){
  let{ id } = useParams();
  let history = useHistory();
  let 찾은상품 = props.shoes.find(function(상품){
    return 상품.id==id
  })

  return(
    <div className="container">
      <div className="row">
        <div className="col-md-6">
          <img src={"https://codingapple1.github.io/shop/shoes"+(찾은상품.id+1)+".jpg"} width="100%" />
        </div>
        <div className="col-md-6 mt-4">
        <h4 className="pt-5">{찾은상품.title}</h4>
          <p>{찾은상품.content}</p>
          <p>{찾은상품.price}</p>
          {/* <h4 className="pt-5">{props.shoes[id].title}</h4>
          <p>{props.shoes[id].content}</p>
          <p>{props.shoes[id].price}</p> */}
          <button className="btn btn-danger">주문하기</button> 
          <button className="btn btn-danger" onClick={()=>{
           // history.goBack() // 뒤로 이동시키기
            history.push('/')//특정 경로로 이동시키기
            // 이런건 검색해서 사용하면된다.
           }}>뒤로가기</button> 
        </div>
      </div>
</div> 
  )
}

export default Detail;
// 변수명 or 함수명 적어주기

이와같은 코드에서

 

<button className="btn btn-danger" onClick={()=>{
           // history.goBack() // 뒤로 이동시키기
            history.push('/')//특정 경로로 이동시키기
            // 이런건 검색해서 사용하면된다.
           }}>뒤로가기</button>

이렇게 사용할 수 있다.

history.goBack()을 사용하면 단순히 뒤로가게되고, push를 사용하면 특정경로를 지정해서 이동 시킬 수 있다.

이것도 Hook이고, useState처럼 중간에 변수로 useHistory()를 불러와 사용한다.

 

-Switch

<Route path="/:id">
   여기를보여준다.
      </Route>

exact를 쓰지않고 해결하는 방식이다. 위와같이하면

/다음에 아무문자,숫자가와도 저 페이지를 보여준다.

<Switch>

<Route path="/">
</Route>

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

<Route path="/:id">
</Route>

</Switch>

이런식으로 라우트를 감싸주면 매칭되는 맨위의것 하나만 보여줄 수 있다.

 

이렇게 안하면 밑에 /:id 는 /다음 모든 문자가오면 다 나오게 된다.

 


데이터바인딩

import,export해온곳에도 마찬가지로 props로 데이터를 전송 할 수 있다.

<Detail shoes={shoes}></Detail>

 

이와같이 Detail.js에서 불러온 컴포넌트에도 props형식을 지켜주고

 

Detail.js안에서 props로 데이터를 사용할 수 있다.

 

그리고 항상 상위컴포넌트에서 하위컴포넌트로 자료를 보내는게 좋기때문에

 

하위컴포넌트에서 data를 만들 수 는 있지만 사용하지 않는게 좋다.

 

URL 파라미터 문법

<Route path="/detail/:id">
<Detail shoes={shoes}></Detail>
{/* 이것도 props는 마찬가지로 쓸 수 있다. */}
</Route>

이와같이 Route안에 Detail 컴포넌트를 넣었는데 :id부분을 변수처럼 URL파라미터로 가져올 수 있다.

id는 다른명칭으로 바꿔도 된다. 갯수는상관없다. /detail/:id/:name 같은 형태도 가능함

 

import React,{useState} from 'react';
import { useHistory,useParams } from 'react-router-dom/cjs/react-router-dom.min';
// 컴포넌트 만들때 꼭 import해오기


function Detail(props){
  let{ id } = useParams();
  // 파라미터값 변수로 저장해서 쓸 수 있다. 여러개가있으면 id,id2,id3..이런식으로 넣어주면댐
  let history = useHistory();
  // react-router-dom 여기들어있다. 훅입니다.
  // 방문기록등을 저장해놓는 object

  //이곳에다가 shoes데이터 Usetate해서 넣어도되지만 app에 넣는게 정석이다.
  //상위->하위컴포넌트로 쓰는게 정석 반대는 어렵기 때문


  let 찾은상품 = props.shoes.find(function(상품){
    return 상품.id==id
  })
  // return오른쪽엔 조건식이가능 이게 참이면 상품 즉 array의 하나가 찾은상품 값으로 들어감
  return(
    <div className="container">
      <div className="row">
        <div className="col-md-6">
          <img src={"https://codingapple1.github.io/shop/shoes"+(찾은상품.id+1)+".jpg"} width="100%" />
        </div>
        <div className="col-md-6 mt-4">
        <h4 className="pt-5">{찾은상품.title}</h4>
          <p>{찾은상품.content}</p>
          <p>{찾은상품.price}</p>
          {/* <h4 className="pt-5">{props.shoes[id].title}</h4>
          <p>{props.shoes[id].content}</p>
          <p>{props.shoes[id].price}</p> */}
          <button className="btn btn-danger">주문하기</button> 
          <button className="btn btn-danger" onClick={()=>{
           // history.goBack() // 뒤로 이동시키기
            history.push('/')//특정 경로로 이동시키기
            // 이런건 검색해서 사용하면된다.
           }}>뒤로가기</button> 
        </div>
      </div>
</div> 
  )
}

export default Detail;
// 변수명 or 함수명 적어주기

이와같이 상단에 param을 불러와 사용해주면된다.

 

<h4 className="pt-5">{props.shoes[id].title}</h4>
          <p>{props.shoes[id].content}</p>
          <p>{props.shoes[id].price}</p>

이와같이 props로 가져와 id값에 param변수를 넣어도 사용하면 되지만 이렇게사용하면

 

추후 정렬된상태에서는 그저 순서대로만 가져오는 문제가 발생한다. 이러한경우는

 

자료의 id값을 활용한다.

export default [
  {
    id : 0,
    title : "White and Black",
    content : "Born in France",
    price : 120000
  },

  {
    id : 1,
    title : "Red Knit",
    content : "Born in Seoul",
    price : 110000
  },

  {
    id : 2,
    title : "Grey Yordan",
    content : "Born in the States",
    price : 130000
  }
]

이렇게 되어있는자료안에 id값을 활용하면 순서가 바뀌어도

 

param값과 일치하는 id의 자료를 가져오면된다.

 

let 찾은상품 = props.shoes.find(function(상품){
    return 상품.id==id
  })

find함수를 사용해도되지만 map이나 filter등 다른걸 사용해도 상관없다.

 

중요한건 같은 id값을, param값과 일치하는 값을 찾아 나타내면 되는거다.

반응형