SvelteKitのsnapshotでページ離脱時の入力内容を復元した話
SvelteKitの snapshot を使うと、ページを離れるときに状態を保存し、ブラウザの「戻る」で戻ったときに復元できます。フォームに入力中に誤って別ページに遷移してしまっても、戻ったときに入力内容が残ります。
仕組み
+page.svelte から snapshot オブジェクトをエクスポートします。
<script lang="ts">
let title = $state('');
export const snapshot = {
// ページを離れるときに呼ばれる(保存したい値を返す)
capture: () => title,
// 戻ってきたときに呼ばれる(保存した値を受け取る)
restore: (value: string) => {
title = value;
},
};
</script>
capture で保存、restore で復元するだけです。値はセッションストレージに保存されます。
実装例:TODOページ
<script lang="ts">
import { enhance } from '$app/forms';
import { beforeNavigate } from '$app/navigation';
let { data, form } = $props();
let title = $state('');
export const snapshot = {
capture: () => title,
restore: (value: string) => {
title = value;
},
};
beforeNavigate(({ cancel }) => {
if (title.trim()) {
if (!confirm('入力中のタスクがあります。離れますか?')) {
cancel();
}
}
});
</script>
<form method="POST" action="?/create" use:enhance>
<input type="text" name="title" bind:value={title} placeholder="タスクを入力" />
<button type="submit">追加</button>
{#if form?.error}
<p style="color: red">{form.error}</p>
{/if}
</form>
動作確認
- TODOページを開いて入力欄に文字を入力する
- 別ページに移動する
- ブラウザの「戻る」で戻る
- 入力した文字が復元されていればOK
複数の値を保存・復元する
複数の値を保存したい場合はオブジェクトにまとめて返します。
<script lang="ts">
let title = $state('');
let priority = $state('medium');
let memo = $state('');
export const snapshot = {
capture: () => ({ title, priority, memo }),
restore: (value: { title: string; priority: string; memo: string }) => {
title = value.title;
priority = value.priority;
memo = value.memo;
},
};
</script>
capture で保存したい値をオブジェクトにまとめて返し、restore で受け取って各変数に代入します。
保存できる値
JSONにシリアライズできる値であれば何でも保存できます。
| 保存できる | 保存できない |
|---|---|
| 文字列・数値・真偽値 | クラスインスタンス |
| 配列 | 関数 |
| プレーンオブジェクト | undefined |
beforeNavigate との使い分け
| 機能 | 役割 |
|---|---|
snapshot |
離脱・復帰時に状態を保存・復元する |
beforeNavigate |
離脱をキャンセルして確認ダイアログを出す |
2つを組み合わせると「確認してから離脱 → 戻ったら復元」という体験が作れます。
まとめ
export const snapshotを+page.svelteからエクスポートするだけで使えるcaptureで保存・restoreで復元する- 複数の値はオブジェクトにまとめて返す
- 値はセッションストレージに保存されるためページリロードでは消える