VueRouterでパスの一部として定義されていないParamsを渡すと、値が消失する
VueRouterでパスの一部として定義されていないParamsを渡すと、値が消失する
事象
Vue Routerでパスの一部として定義されていないparamsを渡そうとしたとき、
以下の警告が発生して、受け渡したParamsの値がundefined
になっていました。
エラーが発生したコード
受渡元
router.push({ name: 'somewhere', params: { hoge: 'i am params' } })
router.ts
{
path: "/somewhere/",
name: "somewhere",
component: somewhere,
props: (route: RouteLocationNormalized) => ({ id: route.params.hoge }),
},
受渡先
import { useRoute } from "vue-router";
const route = useRoute();
const q = route.params.id;
エラー内容
[Vue Router warn]: Discarded invalid param(s) "q" when navigating. See https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22 for more details.
エラー要約
結論
v4.1.4から[パスの一部として定義されていないパラメータを渡す]ことは廃止になりました。
代替手段としては以下を使ってくださいとのこと。
- ストアにデータを保持する
- ルートのパスにデータを定義するか、クエリパラメータとして渡す
- History API stateにデータを保存する
- ナビゲーションガードのなかでto.metaプロパティにデータを渡す
背景
参考文献内容
This change will break your app. This behavior has worked in some scenarios but has been advised against for years as it's an anti-pattern in routing for many reasons, one of them being reloading the page lose the params.
要約
この変更によってアプリが壊れる可能性があります。この振る舞いは一部のシナリオで機能していましたが、ルーティングにおいて反パターンとされており、ページの再読み込みによりパラメータが失われるため、多くの理由から長年にわたって推奨されていませんでした。
代替手段
ストアにデータを保持させる
Piniaなどの状態管理ライブラリを使いましょう。
ルートのパスにデータを定義するか、クエリパラメータとして渡す
router.tsを以下のように変える
router.ts
{
path: "/somewhere/:id",
name: "somewhere",
component: somewhere,
props: (route: RouteLocationNormalized) => ({ id: route.params.hoge }),
},
History API stateにデータを保存する
文献によると、以下のように書けば渡せる(動作未確認)
state
to save it to the History API state
<router-link :to="{ name: 'somewhere', state: { myData } }">...</router-link>
<button
@click="$router.push({ name: 'somewhere', state: { myData } })"
>...</button>
ナビゲーションガードのなかでto.metaプロパティにデータを渡す
参考文献の以下コードのようにする
router.beforeEach(async to => {
if (to.meta.shouldFetch) {
// name `data` whatever you want
to.meta.data = await fetchSomething()
}
})
参考文献
Discussion