-
Notifications
You must be signed in to change notification settings - Fork 56
useDocument merge() calls without save() - clients expect automatic persistence #1188
Copy link
Copy link
Open
Description
Problem Description
Clients are generating code that calls merge() without save(), expecting the changes to be automatically persisted to the database. However, merge() is designed as a setState replacement for local updates (e.g., every keystroke) and does not automatically save to the database.
Example Code
import React from "react"
import { useFireproof } from "use-fireproof"
export default function PageToggle() {
const { database, useDocument } = useFireproof("page-toggle-db")
const { doc, merge } = useDocument({ isWhite: false, type: "page-state" })
const togglePage = () => {
merge({ isWhite: !doc.isWhite }) // ❌ Changes local state but doesn't persist
}
return (
<div>
<button onClick={togglePage}>Toggle Page</button>
<div style={{ backgroundColor: doc.isWhite ? 'white' : 'black' }}>
Current state: {doc.isWhite ? 'White' : 'Black'}
</div>
</div>
)
}Current Behavior vs Expected Behavior
Current Behavior:
merge()updates local component state only- Changes are lost on page refresh/component unmount
- Requires explicit
save()call for persistence
Expected Behavior (by clients):
merge()changes should be automatically persisted- State should survive page refreshes
- No manual
save()required for simple state updates
Impact
This creates a poor developer experience where:
- Clients write code that appears to work (UI updates)
- Data is lost unexpectedly on refresh
- Confusion about when persistence actually happens
- Need to remember to call
save()for everymerge()
Potential Solutions
Option 1: Auto-save with Debouncing
Add automatic persistence to merge() with configurable debouncing:
const { doc, merge } = useDocument({
isWhite: false
}, {
autoSave: true, // Enable auto-save on merge
autoSaveDelay: 300 // Debounce delay in ms
});Option 2: Auto-save on Unload
Automatically save pending changes when component unmounts or page unloads:
// Save any pending changes on cleanup
useEffect(() => {
return () => {
if (hasUnsavedChanges) {
save();
}
};
}, []);Recommended Approach
Option 1 + 2 (Auto-save with Debouncing) seems most practical:
- Maintains backward compatibility
- Provides expected behavior for simple use cases
- Allows opt-out for performance-sensitive scenarios
- Handles both frequent updates and state changes appropriately
Implementation Considerations
- Performance: Auto-save should be debounced to avoid excessive database writes
- Error Handling: Failed auto-saves should not break the UI
- Opt-out: Developers should be able to disable auto-save for performance-critical components
- Migration: Existing code should continue to work unchanged
- Documentation: Clear guidance on when to use auto-save vs manual save
Related Files
use-fireproof/react/use-document.ts(line 65-68: merge implementation)notes/use-document.md(documentation of current behavior)
This issue affects developer experience and could prevent adoption due to unexpected data loss.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels