Most user actions succeed, so update the UI first and confirm later.
Example: When a user checks a todo item, we mark it as complete instantly and sync with the server in the background.
✔ Faster feedback.
✔ Better perceived performance.
✔ More responsive apps
React provides useOptimistic to override UI state while a transition or form action is in progress.
It behaves like useState, but is scoped to a pending transition — perfect for optimistic updates.
function Todo({ todo }) {const [isComplete, setIsComplete] = useOptimistic(todo.isComplete)return (<formaction={async () => {setIsComplete(!isComplete) // Optimistic updateawait updateTodo(todo.id, !isComplete) // Server sync}}><label><input type="checkbox" checked={isComplete} />{todo.text}</label></form>)}
✔ UI updates instantly.
✔ Rolls back automatically if props change.
✔ No manual error handling required for basic cases
Problem: After submitting a form, users wait before seeing the new data — which feels slow.
Solution: Render an optimistic version of the data instantly.
action={async (formData) => {const optimisticPokemon = createOptimisticPokemon(formData)setOptimisticPokemon(optimisticPokemon)const realPokemon = await updatePokemon(formData)setSelectedPokemon(realPokemon.name)setOptimisticPokemon(null)}}
✔ Shows immediate feedback.
✔ Replaces with real data later.
For actions with multiple steps, useOptimistic enables progressive feedback:
function CreateForm() {const [message, setMessage] = useOptimistic('Create')return (<formaction={async (formData) => {setMessage('Creating...')const pokemon = await updatePokemon(formData)setMessage('Saving...')await savePokemon(pokemon)setMessage('Finalizing...')await notifyFleet(pokemon)}}><SubmitButton message={message} /></form>)}
✔ Clear progress feedback.
✔ Keeps users informed.
useOptimistic overrides UI state during transitions"...") for fields not yet loaded