@@ -575,6 +575,21 @@ insert([
575
575
{ text: "Buy groceries", completed: false },
576
576
{ text: "Walk dog", completed: false },
577
577
])
578
+
579
+ // Insert with optimistic updates disabled
580
+ myCollection.insert(
581
+ { text: "Server-validated item", completed: false },
582
+ { optimistic: false }
583
+ )
584
+
585
+ // Insert with metadata and optimistic control
586
+ myCollection.insert(
587
+ { text: "Custom item", completed: false },
588
+ {
589
+ metadata: { source: "import" },
590
+ optimistic: true // default behavior
591
+ }
592
+ )
578
593
` ` `
579
594
580
595
##### ` update `
@@ -598,6 +613,27 @@ update([todo1.id, todo2.id], (drafts) => {
598
613
update(todo.id, { metadata: { reason: "user update" } }, (draft) => {
599
614
draft.text = "Updated text"
600
615
})
616
+
617
+ // Update without optimistic updates
618
+ update(
619
+ todo.id,
620
+ { optimistic: false },
621
+ (draft) => {
622
+ draft.status = "server-validated"
623
+ }
624
+ )
625
+
626
+ // Update with both metadata and optimistic control
627
+ update(
628
+ todo.id,
629
+ {
630
+ metadata: { reason: "admin update" },
631
+ optimistic: false
632
+ },
633
+ (draft) => {
634
+ draft.priority = "high"
635
+ }
636
+ )
601
637
` ` `
602
638
603
639
##### ` delete `
@@ -611,6 +647,67 @@ delete([todo1.id, todo2.id])
611
647
612
648
// Delete with metadata
613
649
delete(todo.id, { metadata: { reason: "completed" } })
650
+
651
+ // Delete without optimistic updates (waits for server confirmation)
652
+ delete(todo.id, { optimistic: false })
653
+
654
+ // Delete with metadata and optimistic control
655
+ delete(todo.id, {
656
+ metadata: { reason: "admin deletion" },
657
+ optimistic: false
658
+ })
659
+ ` ` `
660
+
661
+ #### Controlling optimistic behavior
662
+
663
+ By default , all mutations (` insert ` , ` update ` , ` delete ` ) apply optimistic updates immediately to provide instant feedback in your UI . However , there are cases where you may want to disable this behavior and wait for server confirmation before applying changes locally .
664
+
665
+ ##### When to use ` optimistic: false `
666
+
667
+ Consider disabling optimistic updates when :
668
+
669
+ - ** Complex server - side processing ** : Inserts that depend on server - side generation (e .g ., cascading foreign keys , computed fields )
670
+ - ** Validation requirements ** : Operations where backend validation might reject the change
671
+ - ** Confirmation workflows ** : Deletes where UX should wait for confirmation before removing data
672
+ - ** Batch operations ** : Large operations where optimistic rollback would be disruptive
673
+
674
+ ##### Behavior differences
675
+
676
+ ** ` optimistic: true ` (default )** :
677
+ - Immediately applies mutation to the local store
678
+ - Provides instant UI feedback
679
+ - Requires rollback if server rejects the mutation
680
+ - Best for simple , predictable operations
681
+
682
+ ** ` optimistic: false ` ** :
683
+ - Does not modify local store until server confirms
684
+ - No immediate UI feedback , but no rollback needed
685
+ - UI updates only after successful server response
686
+ - Best for complex or validation - heavy operations
687
+
688
+ ` ` ` typescript
689
+ // Example: Critical deletion that needs confirmation
690
+ const handleDeleteAccount = () => {
691
+ // Don't remove from UI until server confirms
692
+ userCollection.delete(userId, { optimistic: false })
693
+ }
694
+
695
+ // Example: Server-generated data
696
+ const handleCreateInvoice = () => {
697
+ // Server generates invoice number, tax calculations, etc.
698
+ invoiceCollection.insert(invoiceData, { optimistic: false })
699
+ }
700
+
701
+ // Example: Mixed approach in same transaction
702
+ tx.mutate(() => {
703
+ // Instant UI feedback for simple change
704
+ todoCollection.update(todoId, (draft) => {
705
+ draft.completed = true
706
+ })
707
+
708
+ // Wait for server confirmation for complex change
709
+ auditCollection.insert(auditRecord, { optimistic: false })
710
+ })
614
711
` ` `
615
712
616
713
## Usage examples
0 commit comments