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

react-routerに入門する

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

インストールするもの

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

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

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

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

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
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

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

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

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

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

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

export default Index

他ページも同様に。

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の下層ページとして実装します。
まずは中身から。

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を書いていくんですが……。
以下、失敗例です(´・ω・`)。

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

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

    <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/

NanayaKto
札幌で仕事をしているフロントエンドエンジニアです。 ねこはいいぞ。
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした