Context Sample
src/routes/+page.svelte :1-9 — FormProvider がフォーム状態を提供し、各 TextField が id をキーに同じ状態を共有。初期値は initial で渡したオブジェクトの name のみ設定済み。src/lib/FormProvider.svelte :6-22 — 親側の状態管理。$state でフォーム値を保持し、独自 API (getValue/setValue/reset) を Context に登録。snapshot() で親から現在値を取得するフックも用意。src/lib/form-context.ts :3-25 — Context ヘルパ。provideFormContext が API を登録し、useFormContext は見つからない場合にフォールバックを返す作り。src/lib/default-form.ts :4-16 — デフォルトのフォーム API を定義。Svelte の writable ストアを裏で使い subscribe も提供するため、Context が無い環境でも単体で動作。src/lib/TextField.svelte :2-25 — useFormContext で Context API を取得し、未登録ならフォールバックを利用。local を $state で保持し、$effect で親側の変更に追従。local = v)しつつ form.setValue で共有状態を更新するため、他フィールドからの更新とも同期。id をラベルとして表示(src/lib/TextField.svelte :28-30)。defaultForm で動作し、subscribe でフォーム全体の監視が可能。FormProvider が in-place に削除、defaultForm はストア差し替えで対応し、いずれもキー指定/全体リセットに対応。useFormContext で getContext が未登録でも undefined を返す点を見落としていたため、フォールバックが効かず form が undefined になっていた。src/lib/form-context.ts :20-22 を修正し、getContext<FormAPI | undefined> の戻り値をチェックして ctx ?? fallback を返すよう変更。これで親が無いケースでも defaultForm が確実に使われる。FormProvider.svelte :6-22 のようにフォームごとに別インスタンスの状態を持たせたいとき、Context ならそのツリー配下だけに API を公開でき、他ページと干渉しない。FormProvider.svelte を複数置けば独立した getValue/setValue を渡せるため、1 つのグローバル store を共有せずに済む。ストア単体だとスコープ分離を自前でラップする必要がある。useFormContext のフォールバックにより TextField.svelte :11-25 は親が無いときも default-form.ts :6-16 で安全に動作。コンポーネント単体のテストやプレビューがしやすく、props で API を受け渡すより記述量が少ない。reset などの拡張を FormProvider に閉じ込められる。グローバル store を直接使うと子が store 構造に強く依存しやすい。