#react-routerとは?
- Reactのルーティングライブラリのデファクトスタンダード
- Reactで擬似的なページ遷移を可能にする
GitHub
https://github.com/ReactTraining/react-router
今回のサンプル
https://github.com/takanorip/react-router-sample
#書き方
まずReactとreact-routerをimportします。
今回はbrowserHistory
を使います。(ブラウザのHistory APIを使ってルーティングします。)
import React, { Component } from 'react';
import { render } from 'react-dom';
import { IndexRoute, Link, Router, Route, browserHistory } from 'react-router';
次にリンク部分を書きます。
リンクを付けたい部分に<Link>
タグを書くだけです。レンダリング後はこの部分にa
タグが入ります。
class App extends Component {
render() {
return (
<div>
<ul>
<li><Link to="/">TOP</Link></li>
<li><Link to="/about">ABOUT</Link></li>
<li><Link to="/works">WORKS</Link></li>
</ul>
<div>
{ this.props.children }
</div>
</div>
);
}
}
最後にレンダリング部分を書きます。
react-routerを使うときは普通に<App />
のように書くのではなくRouter
とRoute
を使用して書きます。
Route
が遷移するページに対応しています。
<IndexRoute >
を使うと/
のときにTOPに飛ばしてくれます。
render((
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Top} />
<Route path="/about" component={About} />
<Route path="/works" component={Works} />
</Route>
</Router>
), document.querySelector('#app'));
###全体
import React, { Component } from 'react';
import { render } from 'react-dom';
import { IndexRoute, Link, Router, Route, browserHistory } from 'react-router';
import styl from './App.styl';
class App extends Component {
render() {
return (
<div className="main">
<ul className="navi">
<li className="navi__bt"><Link to="/">TOP</Link></li>
<li className="navi__bt"><Link to="/about">ABOUT</Link></li>
<li className="navi__bt"><Link to="/works">WORKS</Link></li>
</ul>
<div className="text">
{ this.props.children }
</div>
</div>
);
}
}
class Top extends Component {
render() {
return <div>Top</div>;
}
}
class About extends Component {
render() {
return <div>About</div>;
}
}
class Works extends Component {
render() {
return <div>Works</div>;
}
}
render((
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Top} />
<Route path="/about" component={About} />
<Route path="/works" component={Works} />
</Route>
</Router>
), document.getElementById('app'));
##注意点
今回 browserHistory
を使用しているため、404になったとき index.html
に戻してあげる設定をする必要があります。
このままだと、その処理が書かれていないので、TOP以外のアドレスを直打ちしたりリロードしたりするとCannot GET /XXX
となってしまいます。
設定方法はサーバーごとに違いますが、
webpack-dev-serverを使うなら --history-api-fallback
という起動オプションを追加すればOKです。
#Reactにおけるルーティングのその他の方法
###ui-router
もともとAngular.jsのルーティングに使用されているモジュールですが、最近Reactでも使えるようになりました。
ui-routerで書くとこんな感じになります。
import React from 'react';
import ReactDOM from 'react-dom';
import UIRouterReact, {UIView, UISref, UISrefActive} from 'ui-router-react';
import stylus from './App.styl';
const router = new UIRouterReact();
const topState = {
name: 'top',
url: '/',
component: () => <div>top</div>
}
const aboutState = {
name: 'about',
url: '/about',
component: () => <div>about</div>
}
const worksState = {
name: 'works',
url: '/works',
component: () => <div>works</div>
}
router.stateRegistry.register(topState);
router.stateRegistry.register(aboutState);
router.stateRegistry.register(worksState);
router.start();
ReactDOM.render(
<div>
<UISrefActive class="active">
<UISref to="top"><a>TOP</a></UISref>
</UISrefActive>
<UISrefActive class="active">
<UISref to="about"><a>ABOUT</a></UISref>
</UISrefActive>
<UISrefActive class="active">
<UISref to="works"><a>WORKS</a></UISref>
</UISrefActive>
<UIView/>
</div>,
document.getElementById('app')
);
###何も使わない
#補足
##v4での書き方
まだ正式にリリースされていませんが、react-router@next(v4)が現在公開されています。
https://react-router.now.sh/
https://github.com/ReactTraining/react-router/tree/v4
v4ではかなり大きな変更があるらしく、書き方も大きく変わります。
上で書いたものをv4版に書き直すと下記のようになります。
import React, { Component } from 'react';
import { render } from 'react-dom';
import { BrowserRouter, Match, Miss, Link } from 'react-router'
class Top extends Component {
render() {
return <div>Top</div>;
}
}
class About extends Component {
render() {
return <div>About</div>;
}
}
class Works extends Component {
render() {
return <div>Works</div>;
}
}
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<ul>
<li><Link to='/'>Top</Link></li>
<li><Link to='/about'>About</Link></li>
<li><Link to='/works'>Works</Link></li>
</ul>
<div className="text">
{ this.props.children }
</div>
<Match exactly pattern='/' component={Top} />
<Match pattern='/about' component={About} />
<Match pattern='/works' component={Works} />
</div>
</BrowserRouter>
);
}
}
render((
<App />
), document.getElementById('app'));