Form Guardian for React
Complete guide to using Form Guardian with React applications. Built on top of @form-guardian/dom with React-specific hooks and utilities.
The useFormAutosave hook is currently unstable and may have issues with certain use cases. For production applications, we recommend using attachFormAutosave from @form-guardian/dom directly, which is more stable and reliable.
🚀 Quick Start
Installation
npm install @form-guardian/react
Peer Dependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
Basic Usage
import { useFormAutosave } from '@form-guardian/react';
function MyForm() {
const { formRef, hasDraft, clearDraft } = useFormAutosave('my-form', {
autoRestore: true,
debounceMs: 500,
});
const handleSubmit = async (e) => {
e.preventDefault();
await clearDraft();
// Submit form...
};
return (
<form ref={formRef} onSubmit={handleSubmit}>
{hasDraft && <div className="alert">Unsaved changes detected</div>}
<input name="name" placeholder="Name" />
<input name="email" type="email" placeholder="Email" />
<button type="submit">Submit</button>
</form>
);
}
📚 What's in this Section
API Reference
Complete API documentation for all React hooks and utilities:
useFormAutosave- Main hook for form autosaveuseDraftStatus- Lightweight draft status tracking- All return types and interfaces
React Hook Form Integration
Complete guide for integrating with React Hook Form:
- Setup and configuration
- Controlled components
- Field-level autosave
- Validation integration
Formik Integration
Complete guide for integrating with Formik:
- Setup and configuration
- Field-level autosave
- Validation handling
Uncontrolled Forms
Working with uncontrolled React components:
- Best practices
- Performance optimization
- Common patterns
Examples & Patterns
Real-world examples and patterns:
- Multi-step forms
- Dynamic fields
- File uploads
- WYSIWYG editors
- Complex validation
🎯 Common Use Cases
Uncontrolled Form (Recommended)
Simple forms without external state management:
import { useFormAutosave } from '@form-guardian/react';
function ContactForm() {
const { formRef, hasDraft, draftTimestamp, clearDraft } = useFormAutosave(
'contact-form',
{ autoRestore: true }
);
return (
<form ref={formRef} onSubmit={async (e) => {
e.preventDefault();
await clearDraft();
// Submit...
}}>
{hasDraft && (
<div className="draft-alert">
Draft from {new Date(draftTimestamp).toLocaleString()}
</div>
)}
<input name="name" />
<input name="email" type="email" />
<textarea name="message" />
<button type="submit">Send</button>
</form>
);
}
React Hook Form
For controlled forms with validation:
import { useForm } from 'react-hook-form';
import { useFormAutosave } from '@form-guardian/react';
import { useEffect } from 'react';
function ProfileForm() {
const { register, handleSubmit, setValue, getValues, watch } = useForm();
const { formRef, restoreValues, clearDraft, saveValues } = useFormAutosave(
'profile-form',
{ autoRestore: false }
);
// Restore on mount
useEffect(() => {
restoreValues(setValue, getValues);
}, []);
// Auto-save on changes
useEffect(() => {
const subscription = watch(() => saveValues());
return () => subscription.unsubscribe();
}, [watch]);
return (
<form ref={formRef} onSubmit={handleSubmit(async (data) => {
await clearDraft();
// Submit data...
})}>
<input {...register('name', { required: true })} />
<input {...register('email', { required: true })} />
<button type="submit">Save</button>
</form>
);
}
Draft Status Indicator
Show draft status anywhere in your app:
import { useDraftStatus } from '@form-guardian/react';
function AppHeader() {
const { hasDraft, updatedAt } = useDraftStatus('contact-form');
return (
<header>
<h1>My App</h1>
{hasDraft && (
<span className="draft-badge">
📝 Draft from {new Date(updatedAt).toLocaleTimeString()}
</span>
)}
</header>
);
}
🔥 Advanced Features
Analytics Events
Track user behavior with comprehensive events:
const { formRef } = useFormAutosave('my-form', {
onBeforeSave: async (values) => {
console.log('Saving draft...', values);
},
onAfterSave: async (values) => {
analytics.track('draft_saved', { formId: 'my-form' });
},
onBeforeRestore: async (values) => {
console.log('Restoring draft...', values);
},
onAfterRestore: async (values) => {
analytics.track('draft_restored', { formId: 'my-form' });
},
onDraftExpired: async (draftId) => {
console.log('Draft expired:', draftId);
},
});
Learn more about Analytics Events →
Batch Saving
Optimize performance by batching saves:
const { formRef } = useFormAutosave('my-form', {
batchSaveInterval: 5000, // Save every 5 seconds
debounceMs: 300,
});
Security
Automatically exclude sensitive fields:
const { formRef } = useFormAutosave('payment-form', {
blacklist: [
'input[type="password"]',
'input[name="cvv"]',
'input[name="cardNumber"]',
],
});
TTL (Time To Live)
Auto-expire drafts after a period:
const { formRef } = useFormAutosave('my-form', {
ttl: { days: 7 }, // Expire after 7 days
onDraftExpired: (draftId) => {
console.log('Draft expired:', draftId);
},
});
📖 Learn More
- API Reference - Complete API documentation
- React Hook Form Guide - Full integration guide
- Examples - Real-world examples
- Best Practices - Tips and pitfalls
🆚 When to Use React Package vs DOM Package
Use @form-guardian/react when:
- ✅ Building React applications
- ✅ Need React hooks API
- ✅ Want draft status in React state
- ✅ Need TypeScript types for React
Use @form-guardian/dom in React when:
- ✅ Want minimal bundle size
- ✅ Don't need React-specific features
- ✅ Already managing refs manually
- ✅ Building custom React wrapper
Both packages work great with React! Choose based on your needs.