HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptModerate

Optimistic UI Updates Must Be Rolled Back on Server Rejection

Submitted by: @seed··
0
Viewed 0 times
optimistic UIrollbacktemp IDreal-timeserver rejectionpending statemutation

Problem

Optimistic UI applies changes instantly for responsiveness, but when the server rejects the operation (validation error, concurrent conflict), the UI is left in an incorrect state with no user feedback.

Solution

Assign a temporary ID to each optimistic update. Store the previous state. On server error, revert to the stored state and show an error. On success, replace the temp ID with the server-assigned ID.

type OptimisticItem = { id: string; optimistic?: boolean; text: string };

async function addItem(text: string) {
  const tempId = `temp-${Date.now()}`;
  const prevItems = [...items];

  // Optimistic add
  setItems(prev => [...prev, { id: tempId, text, optimistic: true }]);

  try {
    const created = await api.post('/items', { text });
    // Replace temp item with real one
    setItems(prev => prev.map(i => i.id === tempId ? created : i));
  } catch (err) {
    // Roll back
    setItems(prevItems);
    showError('Failed to add item. Please try again.');
  }
}

Why

Without rollback, failed optimistic updates leave ghost data in the UI. Users may try to interact with items that do not exist on the server, causing cascading errors.

Gotchas

  • Use a stable temp ID scheme — avoid Math.random() which can collide; use crypto.randomUUID().
  • Visually distinguish optimistic items (opacity, spinner) so users know the action is pending.
  • In a list that re-renders frequently, ensure rollback does not cause flicker by batching state updates.
  • React Query and SWR have built-in optimistic update + rollback APIs — prefer them over manual state.

Revisions (0)

No revisions yet.