35
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

react-router-domのSwitchコンポーネントは必要なんでしょうか。別になくとも動くんですが、という疑問から書き始めた文章です。

Switchコンポーネントがなくても動く

この場合も普通に動作します。

import React from 'react'
import { BrowserRouter, Route, Link } from 'react-router-dom'
import Home from './Home'
import About from './About'
import Dashboard from './Dashboard'

const App = () => {
  return (
    <BrowserRouter>
      <Route exact path="/">
        <Home />
      </Route>
      <Route path="/about">
        <About />
      </Route>
      <Route path="/dashboard">
        <Dashboard />
      </Route>
      <Link to="/">Back To Home</Link>
    </BrowserRouter>
  )
}

問題が起こりうる状況

問題が発生するのは以下のような場合です。

userのidとかをpath parameterとして渡したい時このようなコードを書くと思います。この場合 <About/><User/> はどちらも/about で表示されてしまいます。

import React from 'react'
import { BrowserRouter, Route, Link } from 'react-router-dom'
import Home from './Home'
import About from './About'
import User from './User'

const App = () => {
  return (
    <BrowserRouter>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/about">
          <About />
        </Route>
        <Route path="/:user" component={User} />
      <Link to="/">Back To Home</Link>
    </BrowserRouter>
  )
}

これはSwitchコンポーネントを親要素とすることで防ぐことができます。

import React from 'react'
import { BrowserRouter, Route, Link, Switch } from 'react-router-dom'
import Home from './Home'
import About from './About'
import User from './User'

const App = () => {
  return (
    <BrowserRouter>
      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/about">
          <About />
        </Route>
        <Route path="/:user" component={User} />
      </Switch>
      <Link to="/">Back To Home</Link>
    </BrowserRouter>
  )
}

しかし、<User /><About /> の兄要素として配置されると/about でも常に<User />が表示されます。

import React from 'react'
import { BrowserRouter, Route, Link, Switch } from 'react-router-dom'
import Home from './Home'
import About from './About'
import User from './User'

const App = () => {
  return (
    <BrowserRouter>
      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/:user" component={User} />
        <Route path="/about">
          <About /> // 表示されない
        </Route>
      </Switch>
      <Link to="/">Back To Home</Link>
    </BrowserRouter>
  )
}

公式ドキュメントを読む

React Router: Declarative Routing for React

Now, if we’re at /about, will start looking for a matching . will match and will stop looking for matches and render . Similarly, if we’re at /michael then will render.

まぁ要は最初にマッチしたコンポーネントをレンダリングするようです。

ちなみに

以下のようなコードだと先に<User />がマッチしてしまうため、<Switch />を使用しても<Dashboard />は表示されません。こんなコードないと思う。

import React from 'react'
import { BrowserRouter, Route, Link, Switch } from 'react-router-dom'
import Home from './Home'
import About from './About'
import User from './User'
import Dashboard from './Dashboard';

const App = () => {
  return (
    <BrowserRouter>
      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/about">
          <About />
        </Route>
        <Route path="/:user" component={User} />
        <Route path="/:id" component={Dashboard} />
      </Switch>
      <Link to="/">Back To Home</Link>
    </BrowserRouter>
  )
}

使うべきなのか?

<Switch />のコードをみる限り、脳死で使えばいいかと問われると素直に頷けない感じがします。仕様から察することができると思いますが、ルーティングのたびに子要素(<Route />)のpropsを順番に検証しているためです(この部分)。そのため、後に配置された要素ほど単純に時間がかかると考えられます。多分。

なので、大規模であればURLを適切に設計し<Switch />を使用しないという選択があってもいいのかなと思います。まぁ本稿の例みたいに極端なのは流石にないだろ。

const App = () => {
  return (
    <BrowserRouter>
      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/about">
          <About />
        </Route>
	// めっちゃたくさんのRouteが配置された場合、末弟のこいつは最後にマッチすることになる。
        <Route path="/:user" component={User} />
      </Switch>
      <Link to="/">Back To Home</Link>
    </BrowserRouter>
  )
}

結論

WebサービスのURL設計って大事だね。

35
22
1

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
35
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?