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週間前にあった(笑