@liorpo/react-hook-form-persist
v1.0.10
Published
A React Hook Form persistence library with TypeScript support
Maintainers
Readme
@liorpo/react-hook-form-persist
A lightweight React Hook Form persistence library. Automatically save and restore form data to localStorage.
Features
- 🔄 Automatic Persistence: Automatically saves form data as users type
- 🗂️ Flexible Storage: Default localStorage with support for sessionStorage or custom storage
- ⏰ Timeout Support: Optional data expiration with cleanup
- 🚫 Field Exclusion: Exclude sensitive fields from persistence
- 📱 SSR Compatible: Works with server-side rendering
- 🎯 TypeScript: Full TypeScript support with proper types
- 🧪 Well Tested: Comprehensive test coverage
Installation
npm install @liorpo/react-hook-form-persistQuick Start
Basic Usage
import { useForm } from "react-hook-form";
import { useFormPersist } from "@liorpo/react-hook-form-persist";
function MyForm() {
const form = useForm({
defaultValues: {
name: "",
email: "",
},
});
const { clear } = useFormPersist("my-form", {
control: form.control,
setValue: form.setValue,
});
return (
<form onSubmit={form.handleSubmit(onSubmit)}>
<input {...form.register("name")} placeholder="Name" />
<input {...form.register("email")} placeholder="Email" />
<button type="submit">Submit</button>
<button type="button" onClick={clear}>
Clear Saved Data
</button>
</form>
);
}Using the Component
import { useForm } from "react-hook-form";
import { FormPersist } from "@liorpo/react-hook-form-persist";
function MyForm() {
const form = useForm({
defaultValues: {
name: "",
email: "",
},
});
return (
<>
<FormPersist form={form} formKey="my-form" />
<form onSubmit={form.handleSubmit(onSubmit)}>
<input {...form.register("name")} placeholder="Name" />
<input {...form.register("email")} placeholder="Email" />
<button type="submit">Submit</button>
</form>
</>
);
}API Reference
useFormPersist
A hook that handles form persistence.
const { clear, isRestoringRef, isSavingRef } = useFormPersist(name, config);Parameters
name(string): Unique identifier for the form data in storageconfig(FormPersistConfig): Configuration object
Returns (UseFormPersistResult)
clear(): Function to manually clear the persisted dataisRestoringRef: RefObject indicating if data is being restoredisSavingRef: RefObject indicating if data is being saved
Configuration Options (FormPersistConfig<T>)
| Option | Type | Default | Description |
| ---------------- | ------------------ | ---------------- | ------------------------------------------- |
| storage | Storage | localStorage | Storage implementation to use |
| control | Control | required | React Hook Form control for watching values |
| setValue | UseFormSetValue | required | React Hook Form setValue for restoring data |
| exclude | string[] | [] | Field names to exclude from persistence |
| onDataRestored | (data: T) => void | - | Callback when data is restored |
| validate | boolean | false | Trigger validation when restoring data |
| dirty | boolean | false | Mark fields as dirty when restored |
| touch | boolean | false | Mark fields as touched when restored |
| timeout | number | - | Data expiration time in milliseconds |
| onTimeout | () => void | - | Callback when data expires |
| debounceDelay | number | 0 | Debounce delay in ms before persisting |
FormPersist
A component that automatically handles form persistence.
<FormPersist form={form} formKey="unique-key" />Props (FormPersistProps<T>)
All props from FormPersistConfig except control and setValue, plus:
| Prop | Type | Required | Description |
| ---------- | ---------------- | -------- | ----------------------------------------------- |
| form | UseFormReturn | Yes | React Hook Form instance from useForm() |
| formKey | string | Yes | Unique identifier for storage (e.g., "form-v1") |
| children | ReactNode | No | Optional child elements to render |
Advanced Usage
Using SessionStorage
import { useFormPersist } from "@liorpo/react-hook-form-persist";
function MyForm() {
const form = useForm();
const { clear } = useFormPersist("my-form", {
control: form.control,
setValue: form.setValue,
storage: sessionStorage, // Use sessionStorage instead of localStorage
});
return <form>...</form>;
}Exclude Sensitive Fields
const { clear } = useFormPersist("my-form", {
control: form.control,
setValue: form.setValue,
exclude: ["password", "confirmPassword"], // Don't persist passwords
});Data Expiration
const { clear } = useFormPersist("my-form", {
control: form.control,
setValue: form.setValue,
timeout: 24 * 60 * 60 * 1000, // 24 hours
onTimeout: () => {
console.log("Form data expired");
},
});Debounced Persistence
const { clear } = useFormPersist("my-form", {
control: form.control,
setValue: form.setValue,
debounceDelay: 500, // Save after 500ms of inactivity
});Custom Storage Implementation
const customStorage = {
getItem: (key: string) => {
// Custom get logic
return localStorage.getItem(key);
},
setItem: (key: string, value: string) => {
// Custom set logic
localStorage.setItem(key, value);
},
removeItem: (key: string) => {
// Custom remove logic
localStorage.removeItem(key);
},
};
const { clear } = useFormPersist("my-form", {
control: form.control,
setValue: form.setValue,
storage: customStorage,
});Validation on Restore
const { clear } = useFormPersist("my-form", {
control: form.control,
setValue: form.setValue,
validate: true, // Trigger validation when data is restored
dirty: true, // Mark form as dirty
touch: true, // Mark fields as touched
});Development
Setup
npm installBuild
npm run buildTest
npm test
npm run test:watch
npm run test:coverageLint
npm run lint
npm run lint:fixGitHub Actions
This repository uses a single CI/CD workflow (.github/workflows/ci.yml) that handles:
Testing: Runs on push to main and pull requests
- Tests against Node.js 22 and 24
- Type checking, linting, formatting, and tests
- Coverage reports uploaded to Codecov
Publishing: Automatically publishes to npm when a release is created
- Requires
NPM_TOKENsecret in repository settings
- Requires
Publishing a New Version
- Update version in
package.json - Create a new GitHub release
- The workflow will automatically test and publish to npm
Acknowledgments
Thanks to the original react-hook-form-persist package for inspiration.
License
MIT - Lior Polak
