티스토리 뷰
react-router는 create-react-app로 react 프로젝트를 생성하여 진행합니다.
1. create-react-app
create-react-app 설치는 [React.JS] CodePen, create-react-app으로 React.JS 개발하기 참고 바랍니다.
create-react-app이 설치가 완료 되었다면, react 프로젝트를 생성합니다.
create-react-app hello-react-router
2. react-router-dom 설치하기
npm install --save react-router-dom
3. react-router 적용하기
create-react-app으로 프로젝트를 만들고, react-router-dom 모듈을 설치했다면, 기본 준비는 끝이 납니다.
이번 프로젝트에서 만들 라우터는 4가지 입니다.
- /: Home 컴포넌트를 보여줍니다.
- /about: About 컴포넌트를 보여줍니다.
- /posts: Post 컴포넌트를 보여줍니다.
- /login: Login 컴포넌트를 보여줍니다.
라우트 컴포넌트들은 routes 폴더를 만들어 그 밑에 정의하였습니다.
Header 컴포넌트
react-router을 만들기 전에, 이동할 url을 화면으로 보여줄 Header 컴포넌트를 만들어 보겠습니다.
src 폴터 밑에 components 폴더를 생성하여, compontents 폴더 밑에 Header.js 파일을 만듭니다.
src/components/Header.js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class Header extends Component {
render() {
return (
<div>
<Link to="/">홈</Link>
<Link to="/about/beomy">소개</Link>
<Link to="/Posts">포스트</Link>
<Link to="/login">로그인</Link>
</div>
);
}
}
export default Header;
- 2번 줄, react-router-dom에서 Link 컴포넌트를 import 합니다.
- 8~10번 줄, Link를 to에 정의된 값으로 url을 변경하여 페이지를 이동시켜 줍니다. (실제로 페이지가 이동 되는 것은 아니고 다시 그려줍니다.)
- 9번 줄, /about/beomy로 url 파마미터를 지정하였습니다. Router 설정에서 :username으로 url 파라미터 라우터 설정을 하였고, 자세한 설명은 About 컴포넌트를 이야기할 때 함께 이야기 하겠습니다.
Router 설정
이제 Header 컴포넌트에서 클릭되어 온 url에 어떠한 컴포넌트를 보여 줄 것인지 정의해야 합니다.
src/App.js를 아래 코드와 같이 수정합니다.
src/App.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Header from './components/Header';
import Home from './routes/Home';
import About from './routes/About';
import Posts from './routes/Posts';
import Login from './routes/Login';
import NoMatch from './routes/NoMatch';
class App extends Component {
render() {
return (
<Router>
<div>
<Header />
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about/:username" component={About}/>
<Route path="/posts" component={Posts}/>
<Route path="/login" component={Login}/>
<Route component={NoMatch}/>
</Switch>
</div>
</Router>
);
}
}
export default App;
- 2번 줄, react-router-dom에서 BrowserRouter, Route, Switch를 import로 가져옵니다. BrowserRouter는 Router라는 이름으로 사용하기 위해 'as'를 사용하였습니다. ([자바스크립트] ES6(ECMA Script6) - export, import 참고)
- 3번 줄, Header 컴포넌트를 import로 가져옵니다.
- 5~9번 줄, url에 맞는 컴포넌트를 보여주기 위해 라우터 컴포넌트들을 import로 가져옵니다.
- 10번 줄, 어떠한 Route도 설정되지 않았을 경우 보여줄 컴포넌트를 import로 가져옵니다.
- 16번 줄, Header 컴포넌트를 보여줍니다.
- 18~22번 줄, Route 설정을 합니다. path에 정의된 경로로 들어올 경우, component에 정의된 컴포넌트를 보여줍니다.
- 18번 줄, exact는 만약 /about으로 들어올 경우, /와 /about이 모두 매칭 되기 때문에 Home 컴포넌트와 About 컴포넌트 두개가 보이게 됩니다. exact를 사용하면, 매칭이 될 경우 하위 라우트 설정을 보지 않게 됩니다.
- 19번 줄, :username으로 url 파마미터를 설정하였습니다.
- 22번 줄, Route가 설정되지 않을 경우, component에 정의된 컴포넌트를 보여줍니다. 22번 줄 처럼 사용하기 위해서는 17, 23번 줄 처럼 Route 컴포넌트를 Switch 컴포넌트 안에 정의 해야 합니다. 이 기능을 사용하여 404 페이지를 커스텀하게 정의할 수 있습니다.
Header 컴포넌트는 항상 보이게 되고, 그 밑으로 url에 맞게 Component가 선택되어 보이게 됩니다.
Home 컴포넌트
/로 접근할 경우 보이게 되는 메인 컴포넌트 입니다.
src/routes/Home.js
import React, { Component } from 'react';
class Home extends Component {
render() {
return (
<div>
홈
</div>
);
}
}
export default Home;
About 컴포넌트
scr/routes/About.js
import React, { Component } from 'react';
class About extends Component {
render() {
return (
<div>
{this.props.match.params.username} 의 소개
</div>
);
}
}
export default About;
- 7번 줄, this.props.match.params.username를 보여줍니다. (App.js의 17번 줄에서 설정한 username 필드명으로 값이 내려옵니다.)
* 참고
크롬의 React 개발자 모드로 props.match.params를 확인 해 보면 아래 그림과 같습니다.
Posts 컴포넌트
scr/routes/Posts.js
import React, { Component } from 'react';
import { Route, Link } from 'react-router-dom';
class Post extends Component {
render() {
return (
<div>
<p>title: {this.props.match.params.title}</p>
<p>id: {new URLSearchParams(this.props.location.search).get('id')}</p>
</div>
);
}
}
class Posts extends Component {
render() {
return (
<div>
<p>포스트</p>
<Link to="/posts/first?id=1">First</Link>
<Link to="/posts/second?id=2">Second</Link>
<Link to="/posts/third?id=3">Third</Link>
<Route
path="/posts/:title"
component={Post} />
</div>
);
}
}
export default Posts;
- 20~22번 줄, Link를 to에 정의된 값으로 url을 변경하여 페이지를 이동시켜 줍니다. to에 정의된 url은 url 파마리터와 쿼리 파라미터가 추가된 url입니다.
- 23~25번 줄, 서브 라우터를 설정합니다.
- 4~13번 줄, 서브 라우터가 출력하는 컴포넌트 입니다. Post 컴포넌트는 서브 라우터가 출력하는 컴포넌트입니다.
- 8번 줄, url 파라미터를 출력합니다.
- 9번 줄, 쿼리 파라미터를 출력합니다. JavaScript가 제공하는 URLSearchParams 함수를 사용하여 쿼리 파라미터를 파싱하였습니다.
* 참고
About 컴포넌트에서 url 파라미터를 얻는 방법을 설명하였습니다. 쿼리 파라미터를 얻는 방법은 props.location.search를 이용해야 합니다.
크롬의 개발자 모드로 props.location를 확인 해 보면 아래 그림과 같습니다.
Login 컴포넌트
이 컴포넌트는 로그인이 안되어 있을 경우 다른 페이지로 redirect 시켜주는 예를 설정하기 위해 작성한 컴포넌트 입니다.
로그인 여부를 체크하는 플래그를 두고, 그 플래그의 값에 따라 redirect 여부를 결정합니다.
src/routes/Login.js
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
class Login extends Component {
isLogin = false;
render() {
return (
<div>
{
!this.isLogin && <Redirect to="/"/>
}
로그인 되었습니다.
</div>
);
}
}
export default Login;
- 2번 줄, react-router-dom에서 Redirect 컴포넌트를 import 합니다.
- 5번 줄, 로그인 상태를 나타내는 임의의 플러그를 선언하였습니다.
- 11번 줄, isLogin이 false일 경우 Redirect 컴포넌트 정의 하여 "/"로 redirect 하도록 작성하였습니다. isLogin이 true일 경우 로그인 되었습니다. 라는 문구가 보이게 됩니다.
NoMatch 컴포넌트
NoMatch 컴포넌트는 정의되지 않은 url로 접근 할 경우 보여주는 컴포넌트 입니다. 예를 들어 /test url을 라우팅 설정이 되어 있지 않기 때문에, /test로 접근 할 경우 NoMatch 컴포넌트를 보여주게 됩니다.
src/routes/NoMatch.js
import React, { Component } from 'react';
class NoMatch extends Component {
render() {
return (
<div>
404
</div>
);
}
}
export default NoMatch;
4. Header 컴포넌트 꾸미기
Header 컴포넌트를 조금 꾸며 보도록 하겠습니다.
Header.css 적용하기
아래과 같이 Header.css 파일을 작성합니다.
src/components/Header.css
.header {
background: #5c7cfa;
display: table;
table-layout: fixed;
width: 100%;
}
.item {
text-align: center;
padding-top: 1rem;
padding-bottom: 1rem;
display: table-cell;
color: white;
text-decoration: none;
font-size: 1.1rem;
}
.item:hover {
background: #748ffc;
}
.item:active, .item.active {
background: white;
color: #5c7cfa;
}
CSS 파일을 작성하였으니, Header 컴포넌트에 적용해 봅시다.
src/components/Header.js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import './Header.css';
class Header extends Component {
render() {
return (
<div className="header">
<Link to="/" className="item">홈</Link>
<Link to="/about/beomy" className="item">소개</Link>
<Link to="/Posts" className="item">포스트</Link>
<Link to="/login" className="item">로그인</Link>
</div>
);
}
}
export default Header;
- 3번 줄, CSS 파일을 import 합니다.
- 8~12번 줄, class를 추가하여 CSS를 적용합니다.
액티브 라우터 스타일 설정하기
현재 활성화된 라우터의 스타일을 적용하기 위해서 NavLink를 사용해 보겠습니다.
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
import './Header.css';
class Header extends Component {
render() {
return (
<div className="header">
<NavLink exact to="/" className="item" activeClassName="active">홈</NavLink>
<NavLink to="/about/beomy" className="item"activeClassName="active">소개</NavLink>
<NavLink to="/Posts" className="item" activeClassName="active">포스트</NavLink>
<NavLink to="/login" className="item" activeClassName="active">로그인</NavLink>
</div>
);
}
}
export default Header;
- 2, 9~12 번 줄, Link 컴포넌트를 NavLink 컴포넌트로 변경하여 줍니다.
- 9~12 번 줄, activeClassName attribute에 활성화 될 경우 적용될 스타일 클래스를 선언해 줍니다.
- 9번 줄, exact를 사용하였는데, 이유는 Router 설정시 exact를 사용했던 이유와 동일 합니다.
예를 들어 /about로 접근했다면 /와 /about 모두 만족하기 때문에 /와 /about 모두 active 스타일이 적용이 됩니다. 하지만 exact를 사용하면, 어떤 NavLink에서 조건을 만족할 경우 다음으로 오는 NavLink에는 active 스타일이 적용되지 않게 됩니다.
5. 소스
소스는 https://github.com/beomy/hello-react-router 에서 확인 할 수 있습니다.
참고
'React.JS' 카테고리의 다른 글
[React.JS] Redux 예제로 살펴보기 (12) | 2017.05.04 |
---|---|
[React.JS] Redux 소개 (0) | 2017.05.03 |
[React.JS] Composition VS Inheritance (0) | 2017.04.25 |
[React.JS] Lifting State Up (0) | 2017.04.24 |
[React.JS] Forms (0) | 2017.04.22 |