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>

動作確認

  1. TODOページを開いて入力欄に文字を入力する
  2. 別ページに移動する
  3. ブラウザの「戻る」で戻る
  4. 入力した文字が復元されていれば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 で復元する
  • 複数の値はオブジェクトにまとめて返す
  • 値はセッションストレージに保存されるためページリロードでは消える
← トップページに戻る