[Next.js] ライブラリ「pathpida」を用いてuseRouterを型付けしてみた

Webエンジニア

はじめに

queryパラメータやpathパラメータは管理が煩雑になりやすく、何かしらのファイルで一元管理したくなるのが普通です。githubで公開されているpathpidaを用いることで、Next.jsでのURLの2重管理は解消され、同時にqueryパラメータを明示的に型付きで記述されることで、この問題の多くは解決されます。

しかし、useRouter側は、この型情報を知らないため、実装上に型アサーションが含まれたり、本来必要なパラメータがrouter.pushに抜けるといった問題は解消できていません。

そこで、ここではuseRouterのラッパーを作り、型情報を渡すことでこれらの問題を解決したものになる。ラッパー内で、ナローイングやワインディングが含まれているため完全に実装になってはいないかも知れないが、参考の一つにしてもらいたいです。

リポジトリは以下にありますので、参考ください。

GitHub - gomorepython/pathpida_use_query_wapper
Contribute to gomorepython/pathpida_use_query_wapper development by creating an account on GitHub.

実装の説明

create-next-appを用いて、プロジェクトを新規に作成します。

# npx create-next-app
✔ What is your project named? … next-app
✔ Would you like to use TypeScript? … No / Yes  #yesと選択
✔ Would you like to use ESLint? … No / Yes.     #yesと選択
✔ Would you like to use Tailwind CSS? … No / Yes #yesと選択したがどちらでもOK
✔ Would you like to use `src/` directory? … No / Yes #yesと選択
✔ Would you like to use App Router? (recommended) … No / Yes #今回はNoと選択
✔ Would you like to customize the default import alias (@/*)? … No / Yes #今回はNoと選択
Creating a new Next.js app in XXXXX (your dir)
# cd next-app
# npm install --save-dev pathpida

 

package.jsonのscriptsを変更します。サーバー起動時にpathpidaの自動生成を実行できるようにします。

useRouterのラッパーであるuseRouterWrapper.tsを作成します。

useRouterWrapperは2つの型をGenericsで受け取り型安全を実現しています。
一つ目の型はrouter.query下のオブジェクトの型を表しており、pathpidaの型を渡すことを想定しています。
二つ目の型は、router.pushするときのqueryの型となります。

次にqueryパラメータを受け取るページを追加していきます。
pagesフォルダ直下に[id].tsxファイルを作成し、以下のように実装します。

pathpidaで実装されている$url()の型をuseRouterWrapperの一つ目の型に渡しているのがわかると思います。
これによって、vscode上で,router.queryの後にhogeがサジェッションすることができるようになります。

最後に、トップページである pages/index.tsxを編集します。
ここでは本来Linkタグで良いところをrouter.pushに置き換えています。

useRouterWrapperの二つ目の型に遷移先のページのqueryパラメータの型を渡すことで、push時の引数を型安全にしています。
図のようにhogeを忘れるとvscode上で警告が出ます。

 

最後に動作確認して終了する

# npm run dev

index.tsxのページでclick_linkをクリックすれば、idページに遷移されることが確認できる

 

最後に

現実装の問題点として、booleanなどの扱いに課題が残っています。
queryパラメータにtrueを渡した場合、コード上ではbooleanと認識されていますが、ランタイムではstring型の”true”が入ってきます。
あくまで参考としていただけると幸いです。

タイトルとURLをコピーしました