Best Practices & Pitfalls
This guide covers best practices for using Form Guardian and common pitfalls to avoid.
Best Practices
Optimize Data Size
Don't save large objects unnecessarily:
// ❌ Wrong - saves entire large object
const { formRef } = useFormAutosave('form', {
autoRestore: true,
});
// Form contains large base64 images, huge JSON objects, etc.
// ✅ Correct - exclude large fields
const { formRef } = useFormAutosave('form', {
autoRestore: true,
blacklist: [
'input[name="large-image"]',
'textarea[name="huge-json"]',
],
});
Set Appropriate TTL
Use appropriate Time To Live based on your use case:
// Short forms (contact, feedback)
ttl: { hours: 24 }
// Medium forms (applications, surveys)
ttl: { days: 7 }
// Long forms (drafts, compositions)
ttl: { days: 30 }
Clear Drafts After Submission
Always clear drafts after successful submission:
const handleSubmit = async (data) => {
try {
await submitForm(data);
await clearDraft(); // ✅ Clear after success
} catch (error) {
// Keep draft if submission fails
console.error('Submission failed, draft preserved');
}
};
Handle Errors Gracefully
const { formRef, restoreDraft } = useFormAutosave('form', {
autoRestore: false,
onRestore: (error) => {
if (error) {
console.error('Failed to restore draft:', error);
// Show user-friendly message
}
},
});
Common Pitfalls
Pitfall 1: Not Disabling Autosave During Submit
Problem: Autosave can trigger during form submission, causing race conditions.
// ❌ Wrong - autosave might trigger during submit
const handleSubmit = async (e) => {
e.preventDefault();
await submitForm();
await clearDraft();
};
Solution: Disable autosave during submission:
// ✅ Correct - disable autosave during submit
const [isSubmitting, setIsSubmitting] = useState(false);
const { formRef, clearDraft, destroy } = useFormAutosave('form', {
autoRestore: true,
});
const handleSubmit = async (e) => {
e.preventDefault();
setIsSubmitting(true);
destroy(); // Stop autosave
try {
await submitForm();
await clearDraft();
} finally {
setIsSubmitting(false);
}
};
Pitfall 2: Race Conditions During Restoration
Problem: Multiple restore operations can conflict.
// ❌ Wrong - multiple restores can conflict
useEffect(() => {
restoreDraft();
restoreDraft(); // Called twice
}, []);
Solution: Use a flag to prevent multiple restores:
// ✅ Correct - prevent multiple restores
const [restored, setRestored] = useState(false);
useEffect(() => {
if (!restored) {
restoreDraft().then(() => setRestored(true));
}
}, [restored]);
Pitfall 3: Saving Large Objects
Problem: Saving large objects can exceed storage limits or cause performance issues.
// ❌ Wrong - saves large base64 images
const { formRef } = useFormAutosave('form', {
autoRestore: true,
});
// Form contains <input type="file"> with large images
Solution: Exclude large fields or save metadata only:
// ✅ Correct - exclude large fields
const { formRef } = useFormAutosave('form', {
autoRestore: true,
blacklist: [
'input[type="file"]',
'textarea[name="large-content"]',
],
});
Pitfall 4: Not Handling Controlled Components
Problem: Using autoRestore: true with controlled components won't update React state.
// ❌ Wrong - won't update React state
const [value, setValue] = useState('');
const { formRef } = useFormAutosave('form', {
autoRestore: true, // Tries to set DOM directly
});
Solution: Use manual restoration for controlled components:
// ✅ Correct - manual restoration for controlled components
const [value, setValue] = useState('');
const { formRef, restoreValues } = useFormAutosave('form', {
autoRestore: false,
});
useEffect(() => {
restoreValues(
(field, val) => setValue(val),
() => ({ value })
);
}, []);
Pitfall 5: Not Clearing Drafts
Problem: Old drafts accumulate and consume storage.
// ❌ Wrong - drafts never cleared
const { formRef } = useFormAutosave('form', {
autoRestore: true,
// No TTL, never cleared
});
Solution: Set TTL and clear after submission:
// ✅ Correct - TTL and manual clearing
const { formRef, clearDraft } = useFormAutosave('form', {
autoRestore: true,
ttl: { days: 7 }, // Auto-expire after 7 days
});
const handleSubmit = async () => {
await submitForm();
await clearDraft(); // Manual clear after submission
};
Pitfall 6: Saving Sensitive Data
Problem: Accidentally saving passwords or sensitive information.
// ❌ Wrong - might save sensitive data
const { formRef } = useFormAutosave('form', {
autoRestore: true,
// No blacklist for sensitive fields
});
Solution: Use blacklist to exclude sensitive fields:
// ✅ Correct - exclude sensitive fields
const { formRef } = useFormAutosave('form', {
autoRestore: true,
blacklist: [
'input[name="password"]',
'input[name="ssn"]',
'input[name="credit-card"]',
'.sensitive-field',
],
});
Performance Tips
- Use appropriate debounce - Longer debounce for large forms
- Limit field tracking - Use
fieldSelectorto track only needed fields - Batch operations - Group multiple field updates
- Monitor storage - Check IndexedDB usage periodically
Security Tips
- Always exclude passwords - Form Guardian does this automatically, but verify
- Use blacklist for sensitive data - Add custom exclusions
- Clear drafts on logout - Remove all drafts when user logs out
- Validate restored data - Don't trust restored data blindly
Next Steps
- 📖 Getting Started - Basic setup
- ⚡ Features - Analytics, batching, cross-tab sync
- 🍳 Cookbook - Advanced recipes
- 📚 API Reference - Complete API documentation