@k8ordo/state

うまく動かないとき

よくつまずく症状と、その原因、直し方をまとめています。エラーの文言で探すときは、ページの中を検索してください。

このページの内容

モジュールを読み込むと「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してもかまいません。

原因

ページが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ではサーバーがクエリを読めないので、この切り替わりは避けられません。

原因

initialCookieが効くのは、渡したuseAppStateだけです。渡していないコンポーネントは、サーバーでは既定値を描きます。@k8ordo/staticには、そもそもリクエストがありません。

直し方

レイアウトで一度だけparseCookies(request.cookies)を呼び、Cookieの状態を使うすべてのコンポーネントへinitialCookieとして渡します。

原因

Cookie Store APIは、CookieにSecureを必ず付けます。Safariは、http://localhostでもSecureのCookieを捨てます。

直し方

開発中も、HTTPSで配信します。

テストで、前のテストの値が残っている

原因

ストアはモジュールの中の登録表に残り、保存した行もブラウザに残ります。

直し方

コンポーネントをアンマウントしてから、resetStateRegistry()を呼びます。そのうえで、storageKeyやcookieNameで行を消します。

テストでURLを変える更新を呼ぶと、テストのページが移動してしまう

原因

誰もnavigateイベントを受け止めていないので、navigation.navigate()がドキュメントの読み込みになっています。

直し方

ルーターの代わりに、テストの中でnavigateイベントを受け止め、event.intercept()を呼びます。

k8ordo

Baselineに入った機能を、制限なく使うReactのライブラリ群。

© 2026 k8o — MIT License

組版:Noto Sans JP / M PLUS 2