Skip to content
state management questions

State Management · 7 of 10senior~1 min

What is optimistic UI and how do you implement it?

#ux#react-query#patterns

Optimistic UI

Optimistic UI means updating the interface immediately on user action - before the server confirms - then reconciling when the response arrives.

Why use it

  • Feels instant to the user even on slow connections.
  • Dramatically improves perceived performance.
  • Used by Twitter/X, GitHub, Gmail for likes, reactions, toggles.

Manual implementation

tsx
function TodoItem({ todo }) { const [optimisticDone, setOptimisticDone] = useState(todo.done); const toggle = async () => { setOptimisticDone(prev => !prev); // update UI immediately try { await api.updateTodo(todo.id, { done: !todo.done }); } catch { setOptimisticDone(todo.done); // rollback on error } }; return <input type="checkbox" checked={optimisticDone} onChange={toggle} />; }

React Query - built-in optimistic updates

tsx
const queryClient = useQueryClient(); const mutation = useMutation({ mutationFn: (updatedTodo) => api.updateTodo(updatedTodo), onMutate: async (updatedTodo) => { await queryClient.cancelQueries({ queryKey: ['todos'] }); // save current state for rollback const previous = queryClient.getQueryData(['todos']); // optimistically update the cache queryClient.setQueryData(['todos'], (old) => old.map(t => t.id === updatedTodo.id ? updatedTodo : t) ); return { previous }; // context for onError }, onError: (err, variables, context) => { // rollback on failure queryClient.setQueryData(['todos'], context.previous); }, onSettled: () => { // refetch to sync with server truth queryClient.invalidateQueries({ queryKey: ['todos'] }); }, });

React 19 - useOptimistic

tsx
const [optimisticTodos, addOptimistic] = useOptimistic( todos, (state, newTodo) => [...state, { ...newTodo, pending: true }] );

The key to good optimistic UI is a solid rollback strategy. Always save the previous state before mutating and restore it on error.

updated

did you know it?

related questions