Help us understand the problem. What is going on with this article?

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

More than 3 years have 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'));
takanorip
都内でフロントエンドエンジニアをやっています。
https://takanorip.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away