Auto-save and restore form data using Local/Session/Custom Storage.
npm install auto-form-sync> Automatically save, restore, and sync form data in the browser - with zero dependencies.
> Ideal for autosaving drafts, restoring lost input, and improving UX - all with one line of code.
---
auto-form-sync is a tiny utility that adds autosave + restore behavior to any HTML form. It listens for input changes and persistently stores values in localStorage, sessionStorage, or any custom storage backend. If the page refreshes, crashes, or navigates away - the form data is restored automatically.
bash
npm install auto-form-sync
`
Or include via
---
โ๏ธ Example (Plain HTML)
`html
`
---
โ๏ธ React Usage
You can directly use autoFormSync inside useEffect hook for simplicity.
`js
import { useEffect, useState } from "react";
import { autoFormSync } from "auto-form-sync";
function LoginForm() {
const [formData, setFormData] = useState({
username: "",
password: "",
});
useEffect(() => {
autoFormSync("#loginForm", {
key: "login-draft",
exclude: ["password"],
onRestore: (restored) => {
const restoredMap = Object.fromEntries(
restored.map((field) => [field.name, field.value])
);
setFormData((prev) => ({
...prev,
...restoredMap,
}));
},
});
}, []);
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
};
return (
);
}
export default LoginForm;
`
Or use the built-in React hook useAutoFormSync to integrate with your forms inside React components.
`js
import { useMemo, useState } from "react";
import { useAutoFormSync } from "auto-form-sync";
function LoginForm() {
const [formData, setFormData] = useState({
username: "",
password: "",
});
const options = useMemo(
() => ({
key: "login-draft",
exclude: ["password"],
onRestore: (restored) => {
const restoredMap = Object.fromEntries(
restored.map((field) => [field.name, field.value])
);
setFormData((prev) => ({
...prev,
...restoredMap,
}));
},
}),
[]
);
useAutoFormSync("#loginForm", options);
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
};
return (
);
}
export default LoginForm;
`
โ
Works with all React versions >=17. No provider or setup needed.
> โน๏ธ Always wrap the options in the useMemo hook when passing them to autoFormSync.
---
โ๏ธ Options
| Option | Type | Default | Description |
| --------------- | ------------------------------------------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------- |
| key | string | generated based on form id or class | Unique key to store form data under. |
| storage | "LocalStorage" \| "SessionStorage" \| customStorage: StorageAdapter | | Where to store data (localStorage, sessionStorage, or custom adapter). |
| debounce | number | 300 | Delay (ms) to wait before saving after input. |
| exclude | string[] \| function[] | [] | Field names, selectors, or functions to exclude. |
| restoreOnLoad | boolean | true | Auto-restore saved values on page load. |
| clearOnSubmit | boolean | true | Clear saved data when form is submitted. |
| serializer | (data) => string | JSON.stringify | Custom serialization (e.g. encrypt). |
| deserializer | (string) => data | JSON.parse | Custom deserialization (e.g. decrypt). |
| onSave | (data) => void | - | Callback when form is saved. |
| onRestore | (data) => void | - | Callback when data is restored. |
| onClear | () => void | - | Callback when data is cleared. |
---
$3
StorageAdapter can be used for customized setup.
`
StorageAdapter {
save(key: string, value: string): void | Promise;
load(key: string): string | Promise | null;
remove(key: string): Promise | void;
}
`
Example
`js
options:{
....,
storage: {
save: (key, value) => {},
load: async (key) => {},
remove: async (key) => {},
}
}
`
๐งช Live Example
`html
`
---
๐งฐ Custom Storage Adapter
Use your own storage system (e.g. IndexedDB, cloud sync):
`js
const customStorage = {
get: async (key) => fetch(/storage/${key}).then((res) => res.text()),
set: async (key, value) =>
fetch(/storage/${key}, { method: "POST", body: value }),
remove: async (key) => fetch(/storage/${key}, { method: "DELETE" }),
};
autoFormSync("#form", {
key: "custom-key",
storage: customStorage,
});
`
---
๐งผ Exclude Fields from Sync
You can skip sensitive or unnecessary inputs:
`js
exclude: [
"password", // by name
(field) => field.type === "file", // custom logic
];
``