Skip to main content

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.

⚠️ Stability Notice

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 autosave
  • useDraftStatus - 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

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,
});

Learn more about Batching →

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

🆚 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.