useOptimistic value reverts before the server action actually resolves

Reactjs·Sep 13, 2026·intermediate·
Quick answer

useOptimistic's optimistic value only stays applied while its underlying transition is still pending — if the update function that changes the real state isn't wrapped in the same transition (e.g. a `startTransition` or a form Action), React reverts to actual state as soon as the surrounding render settles, not when the async work finishes.

What causes this error

useOptimistic shows a temporary value only for the duration of the transition that triggered it. If the actual state-updating call isn't part of that same transition — for example, it's fired in a plain `async` click handler instead of a Server Action or `startTransition` — React has no pending transition to tie the optimistic value to, and it snaps back to real state almost immediately.

The Fix

// Wrong — optimistic update and real update aren't in the same transition
function Likes({ likes, addLike }) {
  const [optimisticLikes, setOptimisticLikes] = useOptimistic(likes);

  async function handleClick() {
    setOptimisticLikes((n) => n + 1);
    await addLike(); // not wrapped — optimistic value reverts before this resolves
  }
}

// Fix — use a Server Action / form Action, which React ties to the transition automatically
function Likes({ likes, addLikeAction }) {
  const [optimisticLikes, setOptimisticLikes] = useOptimistic(likes);

  async function action() {
    setOptimisticLikes((n) => n + 1);
    await addLikeAction();
  }

  return (
    <form action={action}>
      <button>{optimisticLikes} likes</button>
    </form>
  );
}

Common causes / variations

  • Calling the real update outside `startTransition`/a form Action instead of inside it
  • The server update failing silently, so React reverts to the (unchanged) real state with no visible error
  • Using `useOptimistic` on state that isn't actually derived from the value being updated

Related errors

See also: useFormStatus must be used within a form, Too many re-renders.

Was this fix helpful?

Comments

Loading comments...