React Router の使い方

React で SPA(シングルページアプリケーション)を作成する場合、アクセスしたURLによってどのコンポーネントを表示するかをアプリ内で制御する必要がありますが、その時に react-router-dom というライブラリを使用します。

前準備

会社のホームページの「トップ」と「会社概要」のページ遷移を例にします。以下のフォルダ構成になるようにファイルを作成しましょう。

React の開発環境は React.js 入門 をご参照ください。以下、webpack-dev-server の利用を前提に進めていきます。
sample_app
    ├  package.json
    ├  webpack.config.js
    ├  index.html
    ├  index.js
    ├  app.js
    ├  top.js // トップページ
    └  about.js // 会社概要ページ

index.html

package.json

{
  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --hot --inline"
  },
  "devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.1",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "webpack": "^3.4.1",
    "webpack-dev-server": "^2.5.1"
  },
  "dependencies": {
    "react": "^15.6.1",
    "react-dom": "^15.6.1"
  }
}

webpack.config.js

const path = require('path')
const publidDir = path.join(__dirname)

module.exports = [
  {
    entry: [
      './index.js'
    ],
    output: {
      path: publidDir,
      publicPath: '/',
      filename: 'bundle.js'
    },
    module: {
      loaders: [{
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          presets: ['react', 'es2015']
        },
      }],
    },
    resolve: {
      extensions: ['.js']
    },
    devServer: {
      contentBase: publidDir,
      historyApiFallback: true
    },
  }
]

HTML5 の History API を使用するので、historyApiFallback を true にする必要があります。

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import App from './app'

ReactDOM.render(<App />, document.getElementById('root'))

これで準備完了です。各ファイルの内容は、React Router の動作確認をするための最低限の内容になっているので味気ないですが、逆に余計なものがなくシンプルでわかりやすくなっています。

React Router のインストール

以下のコマンドを実行してインストールします。

$ npm install --save react-router-dom

投稿時点では v4.2.2 がインストールされたので、以下はバージョン4の仕様に沿って説明を進めます。

ルーティングの設定

app.js の中身を作成し、アクセスしたURLによってトップページ(top.js)と会社概要ページ(about.js)のコンポーネントを切り替える処理を書いていきます。以下のソースをコピペして下さい。

app.js

import React from 'react'
import About from './about'
import Top from './top'

import {
  BrowserRouter as Router,
  Route,
  Link,
  Switch,
} from 'react-router-dom'

const App = () => (
  <Router>
    <div>
      <ul>
        <li><Link to="/">ホーム</Link></li>
        <li><Link to="/about">About</Link></li>
      </ul>
      <Route exact path="/" component={Top} />
      <Route path="/about" component={About} />
    </div>
  </Router>
)
export default App

react-router-dom を import して実際にルーティングの設定をしています。設定の仕方は簡単で、まず切り替える対象のコンポーネントの全体を BrowserRouter のエイリアスとして読み込んだRouter タグで囲みます。 次に、Router タグの中で Route タグを使用し、どのパスにどのコンポーネントを割り当てるかを指定します。あとは本来の <a href=”…”> を <Link to=”…”> に変更すればルーティングの設定は完了です。

ちなみに、最初の Route タグ に exact がついているのは、これがないと “/” が全てのパスにマッチしてしまうからです。”/about” にはついてませんが、これは実は “/about” で始まる URL すべてにマッチしてしまうので、必要ならつけるようにしましょう。

では top.js と about.js の中身を作成して、localhost:8080 にアクセスしてみましょう。

top.js

import React from 'react'

const Top = () =>(
  <h1>トップページです</h1>
)

export default Top

about.js

import React from 'react'

const about = () =>(
  <h1>会社概要ページです</h1>
)

export default about

それぞれ h1 タグがあるだけのとてもシンプルなページです。リンクをクリックすると、HTMLの読み込みはされずに DOM のみが変更されているのが確認できると思います。

また、ブラウザのアドレスバーに localhost:8080/about を直接入力してアクセスすると、きちんと会社概要ページが表示されることも確認しましょう。

404ページを表示する

設定していないURLにアクセスがあった時に表示するコンポーネントも指定できます。まず、404用のページを作成します。

404.js

import React from 'react'

const NotFound = () =>(
  <h1>Not Found</h1>
)

export default NotFound

次に、app.js で 404.js を読み込み、以下のように設定します。

import NotFound from './404'
...

...
      <Switch>
        <Route exact path="/" component={Top} />
        <Route path="/about" component={About} />
        <Route component={NotFound} />
      </Switch>

ポイントは Route タグを Switch タグで囲んでいるところと、404用のコンポーネントに path を指定しないことです。これで、適当なURLにアクセスして 404.js が表示されるか確認してみましょう。

クエリを受け取る

URLに付与された ? 以降の情報を取得してみます。?以降の文字列を自分でパースするのもよいですが、便利なライブラリがあるので今回はそちらを使用します。

$ npm install --save query-string

ここでは localhost:8080?id=1&from=ad という URL でアクセスされた時に、id と from の値を取得するのを例にします。アクセスしたURL情報は、割り振られたコンポーネントの props に入っているので、top.js を以下のように書き直して props の中身を確認してみましょう。(グローバルオブジェクトにも location がセットされているので、そちらを使用しても可能です)

top.js

import React from 'react'

const Top = (props) => {
  console.log(props.location.search) // ?id=1&from=ad
  // console.log(location.search) グローバルオブジェクトでも取得できます
  return (
    <h1>トップページです</h1>
  )
}

export default Top

props.location.search に ?id=1&from=ad という情報が入っているので、こちらの文字列をquery-string を使ってパースします。

import React from 'react'
import queryString from 'query-string'

const Top = (props) => {
  const params = queryString.parse(props.location.search)
  console.log(params) // {from: "ad", id: "1"}
  return (
    <h1>トップページです</h1>
  )
}

export default Top

{from: “ad”, id: “1”} という形で取得することができました。

ルーティングに一致する情報を取りだす

Rest API でよくあると思いますが、/users/:id の id の値を取得したい場合があります。今回は仮に /about/:id というルーティングを設定して、id の値を取得してみます。

まず、app.js の /about のルーティング情報を以下のように変更します。

<Route path="/about/:id" component={About} />

次に、 about.js で id 情報を受け取りますが、URL情報のマッチ情報はコンポーネントの props に入ってきているので、about.js を以下のように書き換えて localhost:8080/about/123 にアクセスしてみてください。

about.js

import React from 'react'

const About = (props) => {
  console.log(props.match.params) // {id: "123"}
  return (
    <h1>会社概要ページです</h1>
  )
}

export default About

props.match.params に id の情報が入っているのが確認できました。

ソースから特定のURLにアクセスする

props に入っている history オブジェクトの push 関数を利用します。たとえば、「/about/1」 にアクセスするには以下のようにします。

this.props.history.push('/about/1')

以上で React Router の説明は終了です。他にもさまざまな機能があるので、一度公式サイトを見ておくのをおすすめします。