Today I Learned ... react.js
🙋♂️ React.js Lecture
🙋 My Dev Blog
React Lecture CH 9
1 - React Router
2 - Link, BrowserRouter
3 - Hash Router, params, withRouter
4 - location, match, history
5 - 쿼리스트링, URLSearchParams
6 - render props, switch, exact
SPA 프레임워크인 React에서는 페이지가 하나지만, 실제로는 여러개인 눈속임을 위해 React-Router
가 필요하다.
react-router
과 reaact-router-dom
을 설치한다.npm i react-router react-router-dom
react-router는 그저 뼈대이고, react-router-dom
이 있어야 웹에서 동작할 수 있다.
(만약 앱에서 사용하려면? react-router-native
를 설치)
우리가 사용하는 것은 react-router-dom이고,
react-router은 react-router-dom가 내부적으로 필요로 하는 것.
지금껏 만들었던 게임들을 한 페이지로 구현해보자.
Games.jsx
import React from 'react';
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import BullsAndCows from './BullsAndCows';
import RSP from './RSP';
import Lotto from './Lotto';
const Games = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/number-baseball" element={<BullsAndCows />} />
<Route path="/rock-scissors-paper" element={<RSP />} />
<Route path="/lotto-generator" element={<Lotto />} />
</Routes>
</BrowserRouter>
);
};
export default Games;
Route path='' component={}
의 형태로 작성해주는데,이제, a태그로 해당 주소로 이동하도록 만들어보자.
단, 보통의 a href=""
로 작성하면 에러가 발생한다.
-> react-router-dom의 Link
를 사용한다.
<Link to="/sub-page" element={<Sub />}>Text</Link>
-> Dev Tool의 Element 탭을 보면, 이는 a
태그로 나와있다.
/number-baseball과 같은 path는 실제로 존재하는 것이 아니므로, 주소창에 직접 입력하거나 새로고침시 `Cannot GET /number-baseball 이라는 에러가 발생함.
-> 주소창에 직접 입력하거나 새로고침 하는 것은, 서버측에 요청을 보내는 것임.
-> Link를 통해서만 이동 가능.(=프론트엔드에서만 동작함)
위 Games.jsx 코드에서 BrowserRouter을 HashRouter로 바꿔본다.
import React from 'react';
import { HashRouter, Routes, Route, Link } from 'react-router-dom';
import BullsAndCows from './BullsAndCows';
import RSP from './RSP';
import Lotto from './Lotto';
const Games = () => {
return (
<HashRouter>
<Link to="/number-baseball">숫자야구</Link>
<Link to="rock-scissors-paper">가위바위보</Link>
<Link to="/lotto-generator">로또생성기</Link>
<Routes>
<Route path="/number-baseball" element={<BullsAndCows />} />
<Route path="/rock-scissors-paper" element={<RSP />} />
<Route path="/lotto-generator" element={<Lotto />} />
</Routes>
</HashRouter>
);
};
export default Games;
http://localhost:8080/#/number-baseball
이런식으로 path 앞에 해시(#)가 붙게 된다.
동작상 큰 차이는 없지만, 새로고침을 해도 화면이 정상적으로 보인다.
(BrowserRouter
에서는 새로고침시 서버에 요청을 하게 되고, 실제 페이지가 아니므로 에러가 발생했었다.)
HashRouter에서는 새로고침시에도 에러없이 동작한다.
URL에서 해시(#) 뒤 부분은 브라우저만 알고 있는 부분.
-> 서버는 해시(#) 뒤 부분을 인식하지 못함.
따라서, 에러가 발생하지 않고 정상 작동.❗️ 서버에선 인식하지 못하므로, SEO(search engine optimizing)에 적합하지 않다.
-> 해시라우터는 실무에서 잘 사용하지 않음.
(** BrowserRouter도 SEO를 위해서는 추가작업 필요하긴 함)
서버 세팅
<Route>
들이 계속해서 많아지게 된다면?GameMatcher.jsx
import React, { Component } from 'react';
export default class GameMatcher extends Component {
render() {
return <div>게임 매쳐</div>;
}
}
Games.jsx
<Route path="/game/:name" element={<GameMatcher />} />
:name
은 실제로 name이 아닌 params
라고 한다. (=파라미터)<Link to="/game/index">게임 매쳐</Link>
params를 임의로 index라고 정하여 Link를 추가해준다.
<Link to="/game/number-baseball">숫자야구</Link>
<Link to="/game/rock-scissors-paper">가위바위보</Link>
<Link to="/game/lotto-generator">로또생성기</Link>
/game/
을 붙여준다.params
가 된다.<Routes>
<Route path="/game/:name" element={<GameMatcher />} />
</Routes>
GameMatcher.jsx
import React, { Component } from 'react';
export default class GameMatcher extends Component {
render() {
console.log(this.props);
return <div>게임 매쳐</div>;
}
}
GameMatcher 컴포넌트 내부에서 this.props
에 저장되어 있다.
컴포넌트 분기.
render() {
if (this.props.match.params.name === 'number-baseball') {
return <NumberBaseball />
} else if (this.props.match.params.name === 'rock-scissors-paper') {
return <RSP />
} else {
return <Lotto />
}
}
* * *
강의 내용이 React Router 6 이전 버전인 것 같아서
이후 내용들은 따로 기록하지 않고, 공식 문서 로 대체하도록 함.