うまく動かないとき
よくつまずく症状と、その原因、直し方をまとめています。エラーの文言で探すときは、ページの中を検索してください。
このページの内容
モジュールを読み込むと「fields must tolerate absence」で投げる
原因
スキーマのフィールドに、.default()も.optional()も付いていません。URLのパラメータやストレージの行はいつでも欠けうるので、定義はそうしたフィールドを読み込みの時点で拒みます。
直し方
エラーに挙がったフィールドに、.default()か.optional()を付けます。zod/miniならz._default()かz.optional()です。エラーがrejects its own defaultsなら、オブジェクト全体の.refine()が、すべてが既定値の状態を受け付けるようにします。
「url boolean fields must use z.stringbool()」で投げる
原因
urlのフィールドか配列の要素に、z.boolean()かz.coerce.boolean()を書いています。URLの"false"をfalseとして読めないので、読み込みの時点で拒まれます。
直し方
z.stringbool()に書き換えます。
「url array fields must default to []」で投げる
原因
urlの配列が、.optional()か、[]以外の既定値を持っています。パラメータが無いことと空の配列は同じURLなので、空の配列を書けなくなります。
直し方
.default([])にします。
Server ComponentでhrefやparseUrlが呼べない
原因
定義を'use client'のファイルからexportしています。Server Componentには、定義そのものではなくclient referenceが届きます。
直し方
定義を、'use client'の無いモジュールに移します。定義は純粋なので、サーバーとクライアントのどちらからimportしてもかまいません。
@k8ordo/staticのビルドが「static build cannot hand a page the search」で止まる
原因
ページがsearchをexportしています。@k8ordo/staticはページをファイルとして書き出すので、クエリごとに違う中身を返せません。
直し方
searchのexportを外し、クエリで変わる部分はクライアントコンポーネントでuseAppStateから読みます。サーバーで読む必要があるなら、@k8ordo/serverに移ります。
update()やhrefが「has no URL serialization」で投げる
原因
urlのフィールドに、URLで表せない値を書こうとしています。たとえばDateです。
直し方
URLに置くのは、文字列と数、真偽値と、それらの配列だけにします。日付は、文字列のまま持ちます。
URLを変えるupdate()で、ページ全体が読み込み直される
原因
ルーターが、Navigation APIの遷移を受け止めていません。今のNext.jsのように受け止めないルーターでは、navigation.navigate()がドキュメントの読み込みになります。
直し方
そのルーターでは、URLの変更をリンクとGETフォームで行います。@k8ordo/routerの上で動く@k8ordo/staticと@k8ordo/serverでは、ドキュメントの読み込みにはなりません。
entryやlocalStorageの真偽値が、書くたびに既定値に戻る
原因
entryやWeb Storage、Cookieのスキーマに、z.stringbool()を書いています。そこでは書いたtrueが型の付いたままスキーマに戻り、文字列を待つz.stringbool()が拒みます。
直し方
z.boolean()に書き換えます。urlから移したフィールドは、綴りも一緒に書き換えます。
再読み込みすると、localStorageの日付が既定値に戻る
原因
Web StorageとCookieの行はJSONで保存されるので、Dateは文字列になって戻ります。z.date()は、その文字列を拒みます。書いた直後に表示されるのは、書き込みがJSONを通らずに描画へ出るからです。
直し方
フィールドを、JSONで表せる型にします。日付なら文字列で持ちます。
別々のはずの2つの状態が、同じ値を見せる
原因
同じ種類の定義に、同じキーを付けています。同じキーの定義は、1つのストアを黙って共有します。@k8ordo/color-schemeも、color-schemeというキーでlocalStorageの状態を使っています。
直し方
キーを、アプリの中で重ならない名前に変えます。キーを変えると保存された値の名前も変わるので、古いキーの値は読まれなくなります。
サーバーの描画で、URLの状態が一瞬既定値になる
原因
サーバーの描画とハイドレーションの描画は、initialUrlを受け取らない限り、urlの既定値で行われます。
直し方
@k8ordo/serverなら、ページでsearchをexportし、受け取った値をinitialUrlとして渡します。ほかのフレームワークなら、parseUrlの結果を渡します。@k8ordo/staticではサーバーがクエリを読めないので、この切り替わりは避けられません。
Cookieに置いた好みが、サーバーの描画に出ない
原因
initialCookieが効くのは、渡したuseAppStateだけです。渡していないコンポーネントは、サーバーでは既定値を描きます。@k8ordo/staticには、そもそもリクエストがありません。
直し方
レイアウトで一度だけparseCookies(request.cookies)を呼び、Cookieの状態を使うすべてのコンポーネントへinitialCookieとして渡します。
開発中のSafariで、Cookieの状態が残らない
原因
Cookie Store APIは、CookieにSecureを必ず付けます。Safariは、http://localhostでもSecureのCookieを捨てます。
直し方
開発中も、HTTPSで配信します。
テストで、前のテストの値が残っている
原因
ストアはモジュールの中の登録表に残り、保存した行もブラウザに残ります。
直し方
コンポーネントをアンマウントしてから、resetStateRegistry()を呼びます。そのうえで、storageKeyやcookieNameで行を消します。
テストでURLを変える更新を呼ぶと、テストのページが移動してしまう
原因
誰もnavigateイベントを受け止めていないので、navigation.navigate()がドキュメントの読み込みになっています。
直し方
ルーターの代わりに、テストの中でnavigateイベントを受け止め、event.intercept()を呼びます。