LoginSignup
23
18

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-10-22

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

何も使わない

補足

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'));
23
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
18