04.React Router
Updated:
1.React Routing 이해하기
- 전통적인 방식인 browser 에서 sever로 무언가 페이지를 요청하는 방식은 URL 의 단위를 바탕으로 server 에 해당 페이지 정보를 받아와서 브라우저에 보여주는 방식임
- React 로 넘어 오면서 한번에 모든 페이지 정보를 가져온 후, 내부에서 URL 에 맞춰서 화면을 보여주는 과정임
SPA 라우팅 과정
1.브라우저 최초에 ‘/’ 경로로 요청을 하면 (root 경로)
2.React Web App 을 내려 줍니다. (서버에서)
3.내려받은 React App 에서 ‘/’ 경로에 맞는 컴포넌트를 보여줍니다. (브라우저에서)
4.React App 에서 다른 페이지로 이동하는 동적을 수행하면,
5.새로운 경로에 맞는 컴포넌트를 보여줍니다
2.SetUp
- 사이트에 상세 페이지 (페이지 나누기) 를 하기 위해서 react-router-dom 라이브러리를 이용함
설치
$ yarn add react-router-dom
-
CRA 에 기본 내장된 패키지가 아닙니다
-
react-router-dom 은 Facebook 의 공식 패키지는 아닙니다.
-
가장 대표적인 라우팅 패키지 입니다.
세팅
- index.js 파일가서 설치된 package 를 import 해줍니다
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
{" "}
// BrowserRouter tag 를 App 에 감싸서 세팅 합니다.
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById("root")
);
BrowserRouter vs HashRouter
-
HashRouter 는 좀더 안전하게 라우팅 할 수 있게 도와줌 주소창에 # 기호를 입력해서 구분해줌. 사이트 주소 뒤에 # 이 붙는데 # 뒤에 적는 적은 서버로 전달 하지 않음
-
BrowserRouter 는 라우팅을 리액트가 아니라 서버에게 요청할수도 있어서 위험할 수 있음 그래서 서버에서 서버 라우팅을 방지하기 위해서 API 를 따로 작성해줘야 함
Route 를 만들기 (페이지 나누기)
// in App.js
import { Link, Route, Switch } from 'react-router-dom'
// 처음 main / 경로는 exact 를 사용해서 정확하게 / 것만 path 로 사용하기 위해 반드시 설정
<Route exact path="/">
<div>main page</div>
</Route>
// 나머지 페이지는 path 에 맞게 localhost/detail 같이 접속이 됨
<Route path="/detail">
<div>detail page</div>
</Route>
// HTML 코드 말고 component 를 route 해주는것 modal 은 component 이름
<Route path="/경로" component={modal}></Route>
3.Dynamic 라우팅
- 개발을 하다보면 url 을 고정적으로 하지 않고 동적으로 처리해서 어떠한 값을 받아와서 component 에서 보여 준다던가, 그 값을 이용해 어떠한 로직을 돌린다던가, 이러한 일들을 하기 위해 dynamic routing 이 필요하게 됨
예를 들어 /profile/1 이라고 특정 페이지를 추가할때 1, 2, 3 계속해서 dynamic 페이지를 생성하려면 아래와 같이 주로 설정 함
// App.js
<Route path="/profile/:id" component={Profile} />
// in profile.jsx
// 여기서 console.log(props) 하게 되면
import React from "react";
export const Profile = (props) => {
console.log(props);
return <div>Profile 페이지 입니다</div>;
};
path 부분에서 :id 를 지정한 후에 해당 {profile} component 를 만들어서 사용할 수 있습니다. (주의: id 값은 type 이 string 이 됨)
// in Profile.jsx
import React from "react";
export const Profile = (props) => {
const id = props.match.params.id;
console.log(id, typeof id);
return (
<>
<h2>Profile 페이지 입니다.</h2>
{id && <p>id 는 {id} 입니다.</p>}
</>
);
};
dynamic routing with query string
- 예제 url localhost:3000/about?name=jacob 이런식으로 정보가 포함되는 dynamic routing 만들기 (optional 한 값을 추가하기)
URLSearchParams 를 사용하기
import React from "react";
export const About = (props) => {
// props 의 데이터 불러오기
const searchParams = props.location.search;
console.log(searchParams);
// new obj 객체 생성
const obj = new URLSearchParams(searchParams);
// name 의 value 값 추출
console.log(obj.get("name"));
return <div>About 페이지 입니다.</div>;
};
- 단점: URLSearchParams 의 method 를 기억하고 사용해야 합니다 / URLSearchParams 가 browser 의 내장 객체이기 때문에 browser 에 따라서 지원하지 않는 경우도 있습니다. (Internet Explore 는 아예 지원 안함)
query-string 라이브러리 사용하기
# 설치
$ yarn add query-string
import React from "react";
// import queryString
import queryString from "query-string";
export const About = (props) => {
const searchParams = props.location.search;
console.log(searchParams);
// queryString.parse() 를 통해서 queryString 추출
const query = queryString.parse(searchParams);
console.log(query);
return (
<>
<h2>About 페이지 입니다.</h2>
{query.name && <p> name 은 {query.name} 입니다. </p>}
</>
);
};
4.Link, History, Switch
4-1. Link
-
기존의 a tag 를 사용하게 되면 페이지가 변경될때마다 sever 에서 data 를 가져 오기 때문에 react 의 특성이 반영 되지 않은 link 이기 때문에 react router dom 의 Link component 를 사용해서 해당 페이지를 이동하게 할 수 있음
-
지금 이동하고자 맞는 경로를 찾는것임
-
React router 를 활용해서 Link 버튼 만들기
NavLink
-
import {NavLink} from 'react-router-dom';
-
activeClassName, activeStyle 처럼 active 상태에 대한 스타일 지정이 가능합니다.
-
Route 의 path 처럼 동작하기 때문에 exact 가 있습니다.
-
일단
안의 버튼에 href 버튼 지우고, 버튼병</Link> 식으로 Link 기능을 통해서 path 와 연결합니다
// 예시..
<Nav.Link> <Link to="/">Home</Link></Nav.Link>
<Nav.Link> <Link to="/detail">Detail</Link></Nav.Link>
4-2. History
-
Link 말고 만약 button 을 눌렀을 경우 페이지를 이동 시키는 방법 (예. 뒤로가기 버튼, 특정 경로로 이동 버튼 만들기)
-
useHistory 라는 hook 을 import
-
useHistory() hook 사용
-
// 버튼을 클릭하면 뒤로가기 가 작동
<button className="btn btn-danger">주문하기</button>
<button className="btn btn-primary" onClick={() => {
history.goBack();
}}>뒤로가기</button>
// 특정
<button className="btn btn-danger">주문하기</button>
<button className="btn btn-primary" onClick={() => {
history.push('/');
}}>홈으로 가기</button>
4-3. Switch
-
Switch component 를 사용하게 되면 여러개가 맞아도 하나만 보여 달라는 의미가 됨
-
모든
를 로 감싸게 되면 여러가지 중에서 하나만 선택에서 보여달라는 의미인것임 -
중복 페이지 연결을 막기위해서 대부분 code 에서는
로 감싼다음에 사용합니다 -
여러 Route 중 순서대로 먼저 맞는 하나만 보여줍니다.
-
exact 를 뺄 수 있는 로직을 만들 수 있습니다.
-
가장 마지막에 어디 path 에도 맞지 않으면 보여지는 컴포넌트를 설정해서, “Not Found” 페이지를 만들 수 있습니다.
// in App.js
// Switch 를 사용해서 가장 큰 범위인 / Home 이 맨아래로 가고 좁은 범위의 순서대로 위에서부터 진행 하면 exact 를 쓰지 않고도 정확하게 경로 설정을 할 수 있음 (단, 맨아래 / 는 exact 를 써줘야 함)
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/profile/:id" component={Profile} />
<Route path="/profile" exact component={Profile} />
<Route path="/about" component={About} />
<Route path="/" exact component={Home} />
{/* 위에서 걸리지 않는 경로가 되기 때문에 Page NotFound 를 사용할 수 있음 */}
<Route component={NotFound} />
</Switch>
</BrowserRouter>
);
}
5.URL parameter
-
참고!! 중요한 data 는 App.js 에 보관하는것을 권장한다. 왜 (그래서 하위 js 파일에서 data 를 사용할때 data biding 을 사용해서 props 로 가져와서 사용하는것을 권장함)
-
그래서 나중에 redux 에 파일을 보관해서 사용하면 상태관리가 훨씬 용이하게 됨
상세페이지 추가로 만들기
예시로..
/detail/0
접속하면 0번째 상품을 보여주고/detail/1
접속하면 1번째 상품을 보여주고/detail/2
접속하면 2번째 상품을 보여주고
하는식의 routing page 을 추가 하는 방법임
-
/detail/:id 는 아무 문자나 받겠다는 URL 작명법
-
콜론 뒤에는 맘대로 작명
-
여러개 사용도 가능함
-
// App.js
{
/* parameter 를 사용하는것 :id 명은 아무거나 해도 됨 */
}
<Route path="/detail/:id">
<Detail shoes={shoes} />
</Route>;
// in Detail.js
// URL 추가를 위해 usePrams import
import { useHistory, useParams } from 'react-router-dom'
// 라우터의 useParams hook : parameter 값을 변수로 만들어서 사용하는 방법
let { id } = useParams(); // app.js 에서 path의 :id 값을 가져감
// 이런식으로 shoes[id] 값에 각 id 값이 할당되서 해당되는 data 의 페이지가 나타나게 됨
<div className="col-md-6 mt-4">
<h4 className="pt-5">{ props.shoes[id].title }</h4>
<p>{ props.shoes[id].content}</p>
<p>{ props.shoes[id].price}</p>
</dic>
-
🔶 근데 Data 의 순서가 바뀐다면 상세페이지도 이상해짐 (예를 들어 상품 페이지를 가나다 순에서 가격순으로 정렬할 경우에 )
- 그럴경우에는 data의 영구번호를 활용해서 routing 을 해줘야 한다. 즉 data 의 id 명이나 고유 번호를 사용해서 위에처럼 순서로 data 를 나열하면 안됨
let { id } = useParams(); // app.js 에서 path의 :id 값을 가
let findGood = props.shoes.find(good => good.id == id)
// 화살표 함수는 parameter 가 1개 일경우에 () 와 {return} 생략 가능
<div className="col-md-6 mt-4">
<h4 className="pt-5">{findGood.title }</h4>
<p>{ findGood.content}</p>
<p>{ findGood.price}원</p>
</div>
설명:
-
find()
를 사용해서 array 안에 원하는 자료를 찾고 싶을 때 사용함 -
find()는 array 뒤에 붙일 수 있으며, 안에 콜백함수가 들어갑니다.
-
콜백함수 내의 파라미터는 (위에선 good) array 안에 있던 하나하나의 데이터를 의미합니다.
-
return 오른쪽엔 조건식을 적을 수 있습니다. 이게 참인 데이터만 새로운 변수에 저장해줍니다.
-
조건식엔 그리고 그걸 현재 URL의 /:id에 적힌 값과 상품의 영구번호 (good).id)가 같은지 비교하고 있는 겁니다.
그래서 /detail/0으로 접속시 찾은상품이라는 변수를 출력해보시면 아마 영구번호가 id : 0인 데이터가 나올겁니다.
/detail/1로 접속시 찾은상품이라는 변수는 영구번호가 id : 1인 데이터일겁니다.
그래서 찾은상품이라는 변수를 이용해서 상품명, 가격 HTML 부분에 데이터바인딩을 했을 뿐입니다.
실제 개발할 땐 그냥 서버에 id : 0인 상품데이터를 Ajax 나 axios 로 요청하는 경우가 많아서 직접 find() 를 사용해서 id 값을 불러 올경우는 많지 않습니다.
🔶 🔷 📌 🔑
Reference
-
react official page- https://reactjs.org/docs/getting-started.html
-
coding apple - https://www.youtube.com/watch?v=LclObYwGj90&list=PLfLgtT94nNq1e6tr4sm2eH6ZZC2jcqGOy
Leave a comment