すべてのリンクに共通のparamを束ねる
ロケールやテナントのように、アプリのほとんどのパスの先頭に付く区間があります。すべてのリンクでその値を渡すのは手間なので、bindParamsで1か所にまとめます。
このページの内容
値を返す関数を渡す
bindParamsには、束ねるparamを返す関数を渡します。返ってくるhrefとnavigateToは、呼ばれるたびにその関数を呼び、足りないparamを補います。
src/links.tsimport { bindParams } from '@k8ordo/router';
import { locales } from './i18n';
export const { href, navigateTo } = bindParams(() => ({
locale: locales.getLocale(),
}));このサイトのsrc/links.tsも、この書き方です。locales.getLocale()は@k8ordo/i18nの関数で、いまのロケールを返します。
アプリのコードは、@k8ordo/routerではなくこのモジュールからhrefとnavigateToをimportします。
束ねたリンクを使う
パターンは/:locale/…と書いたままにします。束ねたlocaleは省けるので、渡すのはそれ以外のparamだけです。コメントの結果は、いまのロケールがjaのときのものです。
import { href, navigateTo } from './links';
href('/:locale/products/:id', { id: '42' }); // '/ja/products/42'
href('/:locale', { locale: 'en' }); // '/en'
navigateTo('/:locale/products');束ねたparamも、渡せば上書きできます。言語の切り替えのように、別のロケールのページを指すリンクで使います。
パターンの綴りを変えないので、Registerによる検査もそのまま効きます。表に無いパターンや、束ねていないparamの渡し忘れは、これまでどおり型エラーになります。
関数は呼ぶたびに読まれる
束ねる関数が呼ばれるのは、bindParamsを呼んだときの1度だけではありません。hrefやnavigateToが呼ばれるたびに呼ばれます。
そのため、リクエストやURLによって変わる値でも、リンクを作るその時点の値が入ります。モジュールのトップレベルで1度だけbindParamsを呼んでおけば十分です。
どのパッケージが値を返すかは、アプリが決めることです。ルーターが知っているのはparamの名前だけで、ロケールが何かは知りません。
オプションは3つ目の引数に渡す
すべてのparamを束ねたパターンでも、navigateToのオプションは3つ目の引数です。2つ目には、paramsの代わりにundefinedを渡します。
navigateTo('/:locale', undefined, { history: 'replace' });
navigateTo('/:locale', { locale: 'en' }, { history: 'replace' });
navigateTo('/:locale', { history: 'replace' });
オプションを2つ目に書くと型エラーになるparamsもオプションもただのオブジェクトなので、2つ目の引数がどちらなのかは、パターンにparamがあるかどうかで決めています。パターンにparamがあれば、2つ目はいつもparamsです。
落とし穴
型の検査をすり抜けてオプションを2つ目に渡すと、paramsとして読まれます。historyは無視され、履歴には新しいエントリが積まれます。