react-router에는 다양한 컴포넌트들이 있는데 그 중에서 우리는 일단 react-router-dom만 사용해보도록하자
npm install react-router-dom
react-router-dom 모듈에서 주로 사용하는 건 HashRouter, BrowserRouter, Router, Link, Switch, Redirect, withRouter, useParams(rrd에서 제공하는 4개의 훅 중 하나) 등이다.
Router들 (HashRouter, BrowserRouter)는 URL을 구동하게 만들어준다. Hash 쪽은 static하게 프론트만 있을 때 주로 사용하고 BrowserRouter는 서버 사이드 렌더링이 존재할 때 주로 사용한다.
이 아래 설명된 속성들은 모두 Router (HashRouter, BrowserRouter) 안에 있어야만 작동한다는 게 포인트다.
Route는 해당 path로 이동 및 컴포넌트를 실행한다.
Switch는 해당 태그 안에 든 Route 중 하나에만 접속하게 해준다.
withRouter는 다른 컴포넌트와 연결하여 props를 전달하기 위해 사용된다
Link는 a태그와 비슷한 역할을 하지만 상태를 유지하면서 페이지를 전환하게 해줍니다. a태그로 움직이면 아예 화면을 새로 렌더링하게 되는 거니까 SPA 를 쓸 이유가 없어지죠!
useParams는 일종의 훅이다. url 정보들을 가져올 수 있다. withRouter를 사용해서 match에서 정보를 가져오는 방법도 있지만 useParams을 활용해서 간단한 정보를 가져오는게 더 빠르고 쉬울 때가 있다.
Redirect는 말 그대로 리다이렉트한다. <Redirect from="*" to="/" />의 경우 모든 곳에서 /로 리다이렉트 함을 의미함.
🚀 라우팅 설정을 할 때 exact를 잘 사용해야 한다. exact는 정확하게 그 경로로 접속해야만 렌더한다는 의미이다. 아래 코드의 경우 /tv에 exact를 주었다. 이 경우 /tv/popular로 접속할 경우 /tv는 렌더링되지 않는다.
최상위 경로인 / 경우에는 exact를 하지 않으면 모든 경우에서 다 실행된다. 경우에 따라 exact를 잘 사용하자.
이들을 사용해서 간단하게 라우팅 설정을 해보자
// header 컴포넌트. styled-component를 적용했습니다.
export default withRouter(({ location: { pathname } }) => (
<Header>
<List>
<Item>
<SLink to="/">Movie</SLink>
</Item>
<Item>
<SLink to="/tv">TV</SLink>
</Item>
<Item>
<SLink to="/search">Search</SLink>
</Item>
</List>
</Header>
));
// routes.js
import React from "react";
import { BrowserRouter, Route, Redirect, Switch } from "react-router-dom";
import Home from "../Routes/Home";
import TV from "../Routes/TV";
import Search from "../Routes/Search";
import Header from "./Header";
export default () => (
<BrowserRouter>
<Header /> // Link가 있기 때문에 반드시 router 내부에 있어야 한다
<Switch>
// Route가 지정한 component에는 자동으로 위치에 대한 props가 주어진다.
<Route path="/" exact component={Home} />
<Route path="/tv" exact component={TV} />
<Route path="/tv/popular" render={() => <h1>Hello guys</h1>} />
<Route path="/search" component={Search} />
<Redirect from="*" to="/" />
</Switch>
</BrowserRouter>
);
// App.js
import React from "react";
import Router from "./Router"; // router.js를 import함
import Header from "./Header";
class App extends React.Component {
render() {
return (
<>
<Router />
</>
);
}
}
export default App;
tip) <></>는 아무 내용도 없는 것이 아니라 Fragments라 하여 여러개의 컴포넌트를 사용할 수 있게 해준다. 상당히 자주 쓰이므로 알아두자
export할 때 다음과 같이 withRouter() 내부로 전달하면 해당 컴포넌트는 props를 가져가기 때문에 유용하다
import { Link, withRouter } from "react-router-dom";
export default withRouter(({ location: { pathname } }) => (
<Header>
<List>
<Item current={pathname == "/" ? true : false}>
<SLink to="/">Movies</SLink>
</Item>
</List>
</Header>
));
Route를 통해 경로로 접근할 수 있는 컴포넌트에서 withRouter로 감싸주면 이용할 수 있는 props를 추출해보았다. 크게 history, location, match로 이루어져 있다. 뒤로가기나 앞으로가기 함수도 들어있으므로 유용하게 처리할 수 있다. 이 객체는 Route가 지정한 component들에는 자동으로 들어있다. 예를 들어 <Route path="/tv" component={TV}>의 경우 TV component 다음 props를 자동으로 가진다.
강제로 이동시키는 history의 push나 match의 path, url, params 등이 자주 이용된다.
history, location, match 와 같은 props를 이용해 리다이렉션을 줄 수도 있다.
다음 코드는 history의 push 메서드를 이용해 팅겨낸 것이다.
props.history.push("/");
이것 외에도 go, goback, replace 등 다양한 메서드가 있으므로 활용하면 된다.
자세한 건 문서를 살펴보자.
(https://reacttraining.com/react-router/web/api/history)
추가!
* Route에 여러 path 지정하기 (v5 부터 가능)
/about, /info로 접근 시 About 컴포넌트를 렌더한다.
<Route path={["/about", "/info"]} component={About} />
* param 넣기
<Route path="/profile/:username" component={Profile} />
* 쿼리 처리하기
location의 serach 부분에 쿼리의 내용이 들어 있습니다. 따로 Route에서 처리하는 방법은 없고, 가까운 param을 렌더하는 컴포넌트에서 location.search를 가져와서 파싱한 다음에 사용하면 됩니다.
http://localhost:3000/about?detail=true&another=1
해당 문자열을 수작업으로(!) 분리할 수도 있겠지만 쿼리 문자열을 객체로 변환하는 qs 라이브러리를 사용합시다.
파싱한 이후에는 원해는 대로 사용하시면 됩니다.
npm i qs
import React from "react";
import qs from "qs";
function About({ location }) {
// qs의 parse를 이용합니다. 뒤의 옵션은 ?를 제거한다는 의미입니다
const query = qs.parse(location.search, { ignoreQueryPrefix: true });
console.log(query);
return (
<div>
<h1>소개</h1>
<p>리액트 라우터 실습</p>
{query.detail === "true" && <p>detail을 true로 주셨습니다</p>}
</div>
);
}
export default About;
* 404 페이지
<Swtich>
<Route render={() => <div>없는 페이지입니다</div>} />
</Swtich>
참고로, () => () 와 () => {} 는 같은 것이되 후자는 return을 요구한다는 점만 다르다.
() => (<div></div>)
() => {return <div></div>}
'React, Next, Redux > ⚛ React.JS' 카테고리의 다른 글
children prop의 사용 (0) | 2020.03.17 |
---|---|
Container + Presenter Pattern 디자인 패턴 (0) | 2020.03.16 |
React 기초 (8) : props를 이용해 redirect하기 (0) | 2020.01.27 |
React 기초 (7) : react-router-dom의 Link를 활용한 네비게이터 (0) | 2020.01.27 |
[React] GitHub Pages로 publish하기 (0) | 2020.01.27 |