react-routerに入門する

数か月前にreact-routerとReduxを同時に学ぼうとして挫折したので、今回はまず順を追ってreact-routerを学習する。

## インストールするもの

vueのときと同じかな？　と最初に何も考えずにreact-routerを入れたのですが、調べるとどうやらこれはコアの部分。
ウェブアプリケーションを構築する為に必要なのは「react-router-dom」の方でした（こちらを入れるとreact-routerも一緒に入ってくれます）。

今回は
react-router-dom　5.0.1
を使用しています。

## まずはApp.jsにざらっと書いてみる

```react:index.js
import React from 'react'
import ReactDOM from 'react-dom'
import './styles.scss'
import App from './App'

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

```react:App.js
import React, { Component } from 'react'
import { BrowserRouter, Route, Link } from 'react-router-dom'

const App = () => (
  <BrowserRouter>
    <h1>react-routerに入門する。</h1>
    <nav>
      <ul>
        <li><Link to='/'>Index</Link></li>
        <li><Link to='/second'>Second</Link></li>
        <li><Link to='/third'>Third</Link></li>
      </ul>
    </nav>
    <article>
      <Route exact path='/' component={Index} />
      <Route path='/second' component={Second} />
      <Route path='/third' component={Third} />
    </article>
  </BrowserRouter>
)

const Index = () => (
  <div>
    <h2>Index</h2>
    <p>インデックスページ</p>
  </div>
)
const Second = () => (
  <div>
    <h2>Second</h2>
    <p>二番目のページです</p>
  </div>
)
const Third = () => (
  <div>
    <h2>Third</h2>
    <p>三番目のページです</p>
  </div>
)

export default App
```

![router1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222505/ea8ea042-d352-272a-fb08-f64491f3511c.gif)

リンクは```<Link to='/'>```で書き、```<Route />```でルーティングを設定すれば良いので、ここまではVueのときと然程遠くない感覚で書けました。
（色々な方の記事を見ていると、BrowserRouterにasで「Router」と付けている人が多いみたいだったんですが何故だろう……）

## ページごとにファイルを分けたい

といってもこれは単に分けるだけ。

```react:pages/Index.js
import React, { Component } from 'react'

const Index = () => (
  <div>
    <h2>Index</h2>
    <p>二番目のページです</p>
  </div>
)

export default Index
```

他ページも同様に。

```react:App.js
import React, { Component } from 'react'
import { BrowserRouter, Route, Link } from 'react-router-dom'
import Index from './pages/Index'
import Second from './pages/Second'
import Third from './pages/Third'

const App = () => (
  <BrowserRouter>
    <h1>react-routerに入門する。</h1>
    <nav>
      <ul>
        <li><Link to='/'>Index</Link></li>
        <li><Link to='/second'>Second</Link></li>
        <li><Link to='/third'>Third</Link></li>
      </ul>
    </nav>
    <article>
      <Route exact path='/' component={Index} />
      <Route path='/second' component={Second} />
      <Route path='/third' component={Third} />
    </article>
  </BrowserRouter>
)

export default App
```

## 動的ルートマッチングしたい

したい。
今回はSecondの下層ページとして実装します。
まずは中身から。

```react:pages/SecondChild.js
import React, { Component } from 'react'

const SecondChild = (props) => {
  const { id } = props.match.params

  return (
    <div>
      <h2>SecondChild</h2>
      <p>{id}のページです</p>
    </div>
  )
}

export default SecondChild
```

次いでApp.jsを書いていくんですが……。
以下、**失敗例**です(´・ω・`)。

```react:App.js
import React, { Component } from 'react'
import { BrowserRouter, Route, Link } from 'react-router-dom'
import Index from './pages/Index'
import Second from './pages/Second'
import SecondChild from './pages/SecondChild'
import Third from './pages/Third'

const App = () => (
  <BrowserRouter>
    <h1>react-routerに入門する。</h1>
    <nav>
      <ul>
        <li><Link to='/'>Index</Link></li>
        <li><Link to='/second'>Second</Link></li>
        <li><Link to='/second/neko'>Second-neko</Link></li>
        <li><Link to='/third'>Third</Link></li>
      </ul>
    </nav>
    <article>
      <Route exact path='/' component={Index} />
      <Route path='/second' component={Second} />
      <Route path='/second/:id' component={SecondChild} />
      <Route path='/third' component={Third} />
    </article>
  </BrowserRouter>
)

export default App
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222505/28b967ea-0821-5701-be19-48c3fab223e4.png)

あれっ、ふたつ出ちゃった。
SecondとSecondChildを逆に書くべきだった？と調べてみるもそういうことではなく。
単純にexactの記載が抜けていたのでした。

```react
    <article>
      <Route exact path='/' component={Index} />
      <Route exact path='/second' component={Second} />
      <Route path='/second/:id' component={SecondChild} />
      <Route path='/third' component={Third} />
    </article>
```

Routeは前方一致するものがあれば全てのコンポーネントが表示されるため、一致させたくないものにはexactが必要です。
これで完全一致の場合のみ表示されるようになります。

## 余談

今回記事を書くにあたって、vue-routerで言うところの```:to={name: 'hoge'}```的な書き方をしたいと思ったのですが、どうにも書き方を見付けられませんでした。
単に見付けられていないのか、そもそもreactでは必要にならないのか……。
触っていくうちに分かると思うので、今後の課題とします。

## 参考記事

react-router@v4を使ってみよう：シンプルなtutorial
https://qiita.com/muiscript/items/b4ca1773580317e7112e

React Roter v4 (RRv4) を使用した時の備忘録
https://blog.kazu69.net/2017/08/10/using-react-router-v4/