1
2

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をvue-routerっぽく使おうとしたら嵌った

Last updated at Posted at 2021-02-16

Vueはそこそこ使い倒していて、Reactもちょっと触っておくかくらいの気持ちで簡単なWebアプリを作っていたら、思わぬところで嵌ったので記事として残しておきます。

経緯

react-router-domを使おうとしたのですが、vue-routerと大分勝手が違ったので、vue-routerと同じような使い方ができる以下のようなコンポーネントを作りました。
ちなみに公式のサンプルを参考にしました。

import loadable from '@loadable/component'
import PropTypes from 'prop-types'
import {
  Switch,
  Route
} from 'react-router-dom'

export const routes = [
  {
    name: 'A画面',
    path: '/',
    component: loadable(() => import('./views/A'))
  },
  {
    name: 'B画面',
    path: '/Bgamen',
    component: loadable(() => import('./views/B'))
  }
]

const RouterView = (props) => {
  const _routes = props.routes || routes
  const routerProps = props
  return (
    <Switch>
        {_routes.map((route, i) =>
            (<Route
                key={i}
                path={route.path}
                render={props => (
                    <route.component 
                        {...props}
                        routes={route.routes}
                        {...routerProps}>
                    </route.component>
                )}/>
            ))
        }
    </Switch>
  )
}
RouterView.propTypes = {
  routes: PropTypes.arrayOf(Object)
}

export default RouterView

vue-routerの<router-view>っぽく、パスが/(ルート)の時にA画面を表示し、/Bgamenの時にB画面を表示するコンポーネントができたぜと思い、使ってみると...

  • /でA画面が表示される
  • /BgamenでもA画面が表示される

という状態でした。

なぜ/BgamenでもA画面が表示されたか

最初は全然検討がつかなくて、色々ググったもののこれといって原因がわからなかったのですが、結論から言うと、実はA画面もB画面も表示されている状態でした。
ルーティングの仕組みだけ勇足で作って、肝心のB画面は空のコンポーネントだったため気付くのに数時間かかりました🥺

react-routerはパスに部分一致したルートを全て表示する仕様で、/Bgamen/にマッチするという動きになっていたようです。

対処方法

Routeコンポーネントにexactプロパティを設定すると完全一致した時のみ表示されるようになります。


const RouterView = (props) => {
  const _routes = props.routes || routes
  const routerProps = props
  return (
    <Switch>
        {_routes.map((route, i) =>
            (<Route
                key={i}
+               exact
                path={route.path}
                render={props => (
                    <route.component 
                        {...props}
                        routes={route.routes}
                        {...routerProps}>
                    </route.component>
                )}/>
            ))
        }
    </Switch>
  )
}

最初はなんでこんな仕様になってるんだと思いましたが、よく考えると小画面を親画面の一部に表示するようなUIだとこの仕様が正しいことに気づきました。
よく言われる、vueは開発者に甘く、reactは厳しいというのを実感しました...

以上です。

PS
この記事投稿した後react-router-domのタグの記事見たらおなじ内容の記事が1週間前にあった(笑

1
2
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?