facebook/react · error · Error

Cannot setState on regular state inside a startGestureTransi

Error message

Cannot setState on regular state inside a startGestureTransition. Gestures can only update the useOptimistic() hook. There should be no side-effects associated with starting a Gesture until its Action is invoked. Move side-effects to the Action instead.

What it means

startGestureTransition(provider, scope) marks updates scheduled inside scope with a transition carrying a gesture flag, and the gesture contract allows only useOptimistic state to change during the gesture phase. requestUpdateLane inspects the current transition for every update; when it has a gesture flag and the update is a regular setState, React throws immediately, because gesture-phase side effects would break the optimistic-update and view-transition model.

Source

Thrown at packages/react-reconciler/src/ReactFiberWorkLoop.js:837

    workInProgressRootRenderLanes !== NoLanes
  ) {
    // This is a render phase update. These are not officially supported. The
    // old behavior is to give this the same "thread" (lanes) as
    // whatever is currently rendering. So if you call `setState` on a component
    // that happens later in the same render, it will flush. Ideally, we want to
    // remove the special case and treat them as if they came from an
    // interleaved event. Regardless, this pattern is not officially supported.
    // This behavior is only a fallback. The flag only exists until we can roll
    // out the setState warning, since existing code might accidentally rely on
    // the current behavior.
    return pickArbitraryLane(workInProgressRootRenderLanes);
  }

  const transition = requestCurrentTransition();
  if (transition !== null) {
    if (enableGestureTransition) {
      if (transition.gesture) {
        throw new Error(
          'Cannot setState on regular state inside a startGestureTransition. ' +
            'Gestures can only update the useOptimistic() hook. There should be no ' +
            'side-effects associated with starting a Gesture until its Action is ' +
            'invoked. Move side-effects to the Action instead.',
        );
      }
    }
    if (__DEV__) {
      if (!transition._updatedFibers) {
        transition._updatedFibers = new Set();
      }
      transition._updatedFibers.add(fiber);
      if (
        hasPotentialUseWarnings() &&
        resolveUpdatePriority() === DiscreteEventPriority
      ) {
        // If we're updating inside a discrete event, then this might be a new user interaction
        // and not just an automatically resolved loading sequence. Don't warn unless it happens again.

View on GitHub (pinned to eafeac097b)

Solutions

  1. Keep only useOptimistic updates inside the startGestureTransition scope — the gesture-driven value must come from the useOptimistic hook
  2. Move every side effect out of the scope callback and into the Action that runs when the gesture commits
  3. If unrelated state must change when the gesture starts, update it before calling startGestureTransition or in the Action, never inside the scope

Example fix

// before
unstable_startGestureTransition(timeline, () => {
  setSelected(true); // regular useState setter — throws
  setOptimisticOffset(dx); // useOptimistic setter — allowed
});

// after
unstable_startGestureTransition(timeline, () => {
  setOptimisticOffset(dx); // useOptimistic only
});
// side effects happen in the Action invoked when the gesture commits
function commitGesture() {
  setSelected(true);
  startTransition(() => setOffset(dragContext.current));
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Calling any non-optimistic state update — a useState setter, useReducer dispatch, context provider write, or external store update that schedules a render — synchronously inside the startGestureTransition scope callback, before the gesture's Action runs.

Common situations: Wiring drag/press gestures where the handler also toggles unrelated UI state (selection, hover, menus) directly in the scope; migrating code from startTransition where side effects were tolerated; experimental builds with enableGestureTransition enabled.

Related errors


AI-assisted analysis of facebook/react@eafeac097b (2026-08-21). Data as JSON: /api/errors/90c7120b49a63c2f. Report an issue: GitHub.