fireproof-storage / fireproof-storage/fireproof

useDocument merge() calls without save() - clients expect automatic persistence

Open
#1,188 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
973
Forks
58
PR merge metrics
No merged PRs in 30d

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

```typescript
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 (


Toggle Page

Current state: {doc.isWhite ? 'White' : 'Black'}


)
}
```

## 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:
1. Clients write code that appears to work (UI updates)
2. Data is lost unexpectedly on refresh
3. Confusion about when persistence actually happens
4. Need to remember to call `save()` for every `merge()`

## Potential Solutions

### Option 1: Auto-save with Debouncing
Add automatic persistence to `merge()` with configurable debouncing:

```typescript
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:

```typescript
// 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

1. **Performance**: Auto-save should be debounced to avoid excessive database writes
2. **Error Handling**: Failed auto-saves should not break the UI
3. **Opt-out**: Developers should be able to disable auto-save for performance-critical components
4. **Migration**: Existing code should continue to work unchanged
5. **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.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.