Skip to main content

Snapshots

Ephemeral DOM state — like scroll positions on sidebars, the content of <input> elements and so on — is discarded when you navigate from one page to another.

For example, if the user fills out a form but navigates away and then back before submitting, or if the user refreshes the page, the values they filled in will be lost. In cases where it's valuable to preserve that input, you can take a snapshot of DOM state, which can then be restored if the user navigates back.

To do this, call snapshot from $app/navigation during component initialization:

+page
<script>
	import { snapshot } from '$app/navigation';

	let comment = $state('');

	snapshot({
		capture: () => comment,
		restore: (value) => (comment = value)
	});
</script>

<form method="POST">
	<label for="comment">Comment</label>
	<textarea id="comment" bind:value={comment} />
	<button>Post comment</button>
</form>
<script lang="ts">
	import { snapshot } from '$app/navigation';

	let comment = $state('');

	snapshot({
		capture: () => comment,
		restore: (value) => (comment = value)
	});
</script>

<form method="POST">
	<label for="comment">Comment</label>
	<textarea id="comment" bind:value={comment} />
	<button>Post comment</button>
</form>

When you navigate away from this page — including via shallow routing — the capture function is called immediately before the page updates, and the returned value is associated with the current entry in the browser's history stack. If you navigate back, the restore function is called with the stored value as soon as the page is updated.

Snapshots must have a unique ID in order to survive across component remounts and page reloads. By default, this is generated from the stack trace when snapshot(...) is called, but you can also explicitly provide an id to (for example) keep snapshots stable across deployments, even if the stack trace differs because of changes to the source code, or to distinguish snapshots created via a shared wrapper function or in multiple instances of the same component:

snapshot<string>(options: {
    id?: string;
    capture: () => string;
    restore: (value: string) => void;
    reset?: () => void;
}): void

A lifecycle function that captures state before navigating and restores it when traversing history.

By default, the snapshot id is generated from the call site. Pass an explicit id to keep snapshots stable across deployments or distinguish multiple uses of a shared helper.

The optional reset callback runs on navigations where there is no captured value to restore, such as when a new history entry is created. Captured values are serialized with the app's transport hook.

snapshot must be called during a component initialization. It remains active as long as the component is mounted.

snapshot
({
id?: string | undefinedid: 'comment', capture: () => stringcapture: () => let comment: stringcomment, restore: (value: string) => voidrestore: (value: stringvalue) => (let comment: stringcomment = value: stringvalue) });

The optional reset callback runs on navigations where there is no captured value to restore, such as when a new history entry is created.

Captured values are serialized with devalue, which handles JSON, objects such as Date and Map, and custom types specified in your transport hook. The serialized data is persisted to sessionStorage, which allows the state to be restored when the page is reloaded, or when the user navigates back from a different site.

Avoid returning very large objects from capture — once captured, objects will be retained in memory for the duration of the session, and in extreme cases may be too large to persist to sessionStorage.

export const snapshot

Legacy mode

Previously, snapshots were created by exporting a snapshot object with capture and restore methods from a +page.svelte or +layout.svelte. This form is deprecated in favour of the snapshot helper, which can be called from any component.

+page
<script>
	let comment = $state('');

	/** @type {import('./$types').Snapshot<string>} */
	export const snapshot = {
		capture: () => comment,
		restore: (value) => comment = value
	};
</script>
<script lang="ts">
	import type { Snapshot } from './$types';

	let comment = $state('');

	export const snapshot: Snapshot<string> = {
		capture: () => comment,
		restore: (value) => comment = value
	};
</script>

Values captured this way are serialized as JSON, and shallow navigations do not capture them.

Edit this page on GitHub llms.txt