Form Wire
Guides

Draft Persistence

Auto-save form progress to localStorage or custom storage

Form Wire can automatically save and restore form drafts, so users don't lose progress on page reload.

Basic Usage

import { createLocalStorageDraftAdapter, createFormWire } from "@form-wire/react";

<Form
  action={submit}
  draftPersistence={{
    key: "form-wire:my-form:draft",
    adapter: createLocalStorageDraftAdapter(),
  }}
/>

The form saves current values on every change and loads them on mount. After a successful submit, the draft is cleared.

Built-in Adapters

createLocalStorageDraftAdapter()

Persists to window.localStorage. Works in the browser only.

createSessionStorageDraftAdapter()

Persists to window.sessionStorage. Draft is lost when the tab closes.

Custom Adapter

Implement the DraftPersistenceAdapter interface:

interface DraftPersistenceAdapter {
  load: (key: string) => Record<string, unknown> | undefined | Promise<Record<string, unknown> | undefined>;
  save: (key: string, values: Record<string, unknown>) => void | Promise<void>;
  clear: (key: string) => void | Promise<void>;
}

Example — persist to an API:

const apiAdapter: DraftPersistenceAdapter = {
  load: async (key) => {
    const res = await fetch(`/api/drafts/${key}`);
    return res.ok ? res.json() : undefined;
  },
  save: async (key, values) => {
    await fetch(`/api/drafts/${key}`, {
      method: "PUT",
      body: JSON.stringify(values),
    });
  },
  clear: async (key) => {
    await fetch(`/api/drafts/${key}`, { method: "DELETE" });
  },
};

Loading State

While a draft is loading, draftLoading is true in the submit/status props. The default submit button shows "Loading draft..." during this phase.

On this page