{"record":{"id":"0b83fcb6efaa5876","repo":"facebook/react","slug":"detected-a-large-number-of-updates-inside-starttra","errorCode":null,"errorMessage":"Detected a large number of updates inside startTransition. If this is due to a subscription please re-write it to use React provided hooks. Otherwise concurrent mode guarantees are off the table.","messagePattern":"Detected a large number of updates inside startTransition\\. If this is due to a subscription please re-write it to use React provided hooks\\. Otherwise concurrent mode guarantees are off the table\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/react-reconciler/src/ReactFiberHooks.js","lineNumber":2250,"sourceCode":"          ) {\n            // Just assert that assumption holds that we're not overriding anything.\n            console.error(\n              'We expected inner Transitions to have transferred the outer types set and ' +\n                'that you cannot add to the outer Transition while inside the inner.' +\n                'This is a bug in React.',\n            );\n          }\n        }\n        prevTransition.types = currentTransition.types;\n      }\n      ReactSharedInternals.T = prevTransition;\n\n      if (__DEV__) {\n        if (prevTransition === null && currentTransition._updatedFibers) {\n          const updatedFibersCount = currentTransition._updatedFibers.size;\n          currentTransition._updatedFibers.clear();\n          if (updatedFibersCount > 10) {\n            console.warn(\n              'Detected a large number of updates inside startTransition. ' +\n                'If this is due to a subscription please re-write it to use React provided hooks. ' +\n                'Otherwise concurrent mode guarantees are off the table.',\n            );\n          }\n        }\n      }\n    }\n  } else {\n    // The original dispatch was not part of a transition.\n    try {\n      const returnValue = action(prevState, payload);\n      handleActionReturnValue(actionQueue, node, returnValue);\n    } catch (error) {\n      onActionError(actionQueue, node, error);\n    }\n  }\n}","sourceCodeStart":2232,"sourceCodeEnd":2268,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react-reconciler/src/ReactFiberHooks.js#L2232-L2268","documentation":"Dev-only warning emitted from runActionStateAction (ReactFiberHooks.js:2250), the queue that replays useActionState actions that were dispatched inside a transition. While a transition is active on ReactSharedInternals.T, every fiber that schedules an update is added to the transition's _updatedFibers set (ReactFiberWorkLoop.js:849). When the outermost action-transition finishes and that set holds more than 10 distinct fibers, React warns: this pattern usually means a subscription is driving updates, and updates React did not plan for cannot be interrupted or time-sliced.","triggerScenarios":"A useActionState/form action dispatched inside startTransition or useTransition whose execution schedules updates on more than 10 distinct fibers: calling setState on many components in a loop, an external-store subscription callback (Redux/Zustand/MobX) firing inside the action, or one dispatch whose reducer fans out to per-component states.","commonSituations":"Wrapping store subscription handlers or event-bus callbacks in startTransition; React 18-to-19 migrations where actions update a dozen widgets; a useEffect subscribed to a mutable store calling wrapped setState inside a transition.","solutions":["Rewrite the subscription with useSyncExternalStore so React owns scheduling and dedupes updates","Batch the fan-out: compute one result inside the transition and call a single setState/dispatch instead of one per component","Move subscription-driven updates outside startTransition; external-store notifications are meant to be sync","If more than 10 updates on distinct components is intentional, accept the dev warning - it flags degraded interruption guarantees, not a crash"],"exampleFix":"// before: subscription fans out inside a transition\nstore.subscribe(() => {\n  startTransition(() => {\n    listeners.forEach(l => l.forceUpdate()); // >10 fibers updated\n  });\n});\n\n// after: React owns the subscription\nconst snapshot = useSyncExternalStore(store.subscribe, store.getSnapshot);","handlingStrategy":"validation","validationCode":"// Dev guard: count updates your code triggers inside one action/transition\nlet fanOut = 0;\nconst track = (dispatch) => (...args) => { fanOut++; return dispatch(...args); };\n\nstartTransition(() => {\n  fanOut = 0;\n  dispatchAction(track(setA), track(setB), track(setC));\n  if (fanOut > 10) {\n    console.warn('Transition fan-out > 10 fibers - rewrite as useSyncExternalStore or batch');\n  }\n});","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use useSyncExternalStore for every external store read instead of manual subscribe/setState","Keep transition scopes to one user-initiated state change","Never run store.notify() or subscription callbacks inside startTransition","Treat this warning as a design smell: transitions expect few, intentional updates"],"tags":["start-transition","use-action-state","use-transition","subscriptions","concurrent-mode","performance","dev-only"],"backgroundTag":"starttransition-too-many-updates","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}