[ fukuoka.ts #4 / 2026.05.07 ]
// SPAに適した新しいルーティングAPI
$ whoami
name —
ブラウザのナビゲーションアクションやアプリケーションの履歴を管理する機能を提供するAPIで、History APIの後継として設計されました。
preventDefault()
history.pushState()
つまり SPA は「ブラウザの遷移を乗っ取って JS で画面を差し替えている」。この仕組みの土台が History API
<Link>
useNavigate()
popstate
next/router
next/navigation
普段意識しないが、裏側では全て History API が動いている。その History API 自体に課題がある
click
history.go(1)
pushState
event.signal
navigate
intercept()
react-router や next/router・link が内部で Navigation API を活用するようになるだけ。ゴリゴリ書く機会は多くない
ページ離脱防止、フォーカス復元、遷移アニメーション — これらは自前で実装する必要がある
入力途中で誤ってブラウザバックしてしまっても、確認ダイアログを表示して意図しないページ離脱を防ぐ
usePreventLeave.ts
useEffect(() => { const handler = (event: NavigateEvent) => { if (!hasUnsavedChanges) return; // SPA 内遷移でも確認ダイアログを表示できる const leave = window.confirm('変更が保存されていません。離れますか?'); if (!leave) event.preventDefault(); }; navigation.addEventListener('navigate', handler); return () => navigation.removeEventListener('navigate', handler); }, [hasUnsavedChanges]);
フォーカスが消失してしまうと、再びtabキーでフォーカスをたどらないといけない
useFocusRestore.ts
// 遷移前にフォーカス位置を state に保存 navigation.updateCurrentEntry({ state: { focusedId: document.activeElement?.id }, }); // 戻ってきたら復元 navigation.addEventListener('currententrychange', () => { const state = navigation.currentEntry.getState(); if (state?.focusedId) { document.getElementById(state.focusedId)?.focus(); } });
遷移前に updateCurrentEntry() でフォーカス中の要素IDを履歴エントリに保存し、戻ってきたら getState() で取り出してフォーカスを復元する
updateCurrentEntry()
getState()
View Transitions API と Navigation API を組み合わせて、スムーズな遷移を SPAで実装
router.ts
navigation.addEventListener('navigate', (event) => { if (!event.canIntercept) return; event.intercept({ handler() { return document.startViewTransition(() => { updateContent(event.destination.url); }).finished; } }); });
navigate イベントでリンククリックもブラウザバックも一括ハンドリング。View Transitions と組み合わせるだけでページ遷移アニメーションが完成する
if ('navigation' in window)
— fin
Navigation API を使ってみよう!
logout