Edited at

react-routerを使ってページ遷移(@第3回 Reactハンズオン 初等部編)

More than 1 year has passed since last update.


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を使ってルーティングします。)


App.js

import React, { Component } from 'react';

import { render } from 'react-dom';
import { IndexRoute, Link, Router, Route, browserHistory } from 'react-router';

次にリンク部分を書きます。

リンクを付けたい部分に<Link>タグを書くだけです。レンダリング後はこの部分にaタグが入ります。


App.js

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 />のように書くのではなくRouterRouteを使用して書きます。

Routeが遷移するページに対応しています。

<IndexRoute >を使うと/のときにTOPに飛ばしてくれます。


App.js

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'));


全体


App.js

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で書くとこんな感じになります。


App.js

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')
);



何も使わない

https://medium.com/@dabit3/beginner-s-guide-to-react-router-53094349669#.hgngpfr9s


補足


v4での書き方

まだ正式にリリースされていませんが、react-router@next(v4)が現在公開されています。

https://react-router.now.sh/

https://github.com/ReactTraining/react-router/tree/v4

v4ではかなり大きな変更があるらしく、書き方も大きく変わります。

上で書いたものをv4版に書き直すと下記のようになります。


App.js

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'));