SvelteKitの$app/navigationでプログラムからナビゲーションを制御した話

SvelteKitでは $app/navigation から関数をインポートすることで、JavaScriptからナビゲーションを制御できます。<a> タグでは対応できない条件付き遷移や離脱確認などに使います。


主な関数

import { goto, beforeNavigate, afterNavigate, invalidate, invalidateAll } from '$app/navigation';
関数 用途
goto(url) 指定URLにプログラムから遷移する
beforeNavigate(fn) 遷移前に処理を実行する(離脱確認など)
afterNavigate(fn) 遷移後に処理を実行する
invalidate(url) 特定のデータを再取得する
invalidateAll() すべてのloadデータを再取得する

goto — プログラムから遷移する

ボタンクリックやフォーム処理の中で遷移したいときに使います。

<script lang="ts">
  import { goto } from '$app/navigation';
</script>

<button onclick={() => goto('/about')}>Aboutへ移動</button>

<a href="/about"> と同じ動きですが、条件分岐やイベントハンドラの中で使えます。

// 条件付き遷移の例
async function handleSubmit() {
  const result = await submit();
  if (result.success) {
    goto('/complete');
  }
}

beforeNavigate — 離脱を確認する

ページを離れる前に処理を挟めます。未保存データがある場合の離脱確認に便利です。

<script lang="ts">
  import { beforeNavigate } from '$app/navigation';

  let title = $state('');

  beforeNavigate(({ cancel }) => {
    if (title.trim()) {
      if (!confirm('入力中のタスクがあります。離れますか?')) {
        cancel();  // 遷移をキャンセル
      }
    }
  });
</script>

<input type="text" bind:value={title} placeholder="タスクを入力" />

cancel() を呼ぶと遷移がキャンセルされます。入力欄が空のときはそのまま遷移します。


invalidateAll — データを手動で再取得する

load 関数を再実行してデータを最新の状態に更新します。

<script lang="ts">
  import { invalidateAll } from '$app/navigation';
</script>

<button onclick={() => invalidateAll()}>🔄 再読み込み</button>

invalidate(url) を使うと特定のfetchだけを再実行できます。

// 特定のAPIのデータだけ再取得
invalidate('/api/posts');

実装例:TODOページ

<script lang="ts">
  import { enhance } from '$app/forms';
  import { goto, beforeNavigate, invalidateAll } from '$app/navigation';

  let { data, form } = $props();
  let title = $state('');

  // 入力中に離れようとしたら確認
  beforeNavigate(({ cancel }) => {
    if (title.trim()) {
      if (!confirm('入力中のタスクがあります。離れますか?')) {
        cancel();
      }
    }
  });
</script>

<button onclick={() => goto('/about')}>Aboutへ移動</button>
<button onclick={() => invalidateAll()}>🔄 再読み込み</button>

<form method="POST" action="?/create" use:enhance>
  <input type="text" name="title" bind:value={title} placeholder="タスクを入力" />
  <button type="submit">追加</button>
</form>

まとめ

関数 使うタイミング
goto 条件付き遷移・イベントハンドラからの遷移
beforeNavigate 未保存データの離脱確認
afterNavigate 遷移後のスクロール位置リセットなど
invalidateAll 手動でデータを最新化したいとき
← トップページに戻る