1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @flow
    
  8.  */
    
  9. 
    
  10. import type {
    
  11.   ReactContext,
    
  12.   StartTransitionOptions,
    
  13.   Usable,
    
  14.   Thenable,
    
  15.   RejectedThenable,
    
  16.   Awaited,
    
  17. } from 'shared/ReactTypes';
    
  18. import type {
    
  19.   Fiber,
    
  20.   FiberRoot,
    
  21.   Dispatcher,
    
  22.   HookType,
    
  23.   MemoCache,
    
  24. } from './ReactInternalTypes';
    
  25. import type {Lanes, Lane} from './ReactFiberLane';
    
  26. import type {HookFlags} from './ReactHookEffectTags';
    
  27. import type {Flags} from './ReactFiberFlags';
    
  28. import type {TransitionStatus} from './ReactFiberConfig';
    
  29. 
    
  30. import {NotPendingTransition as NoPendingHostTransition} from './ReactFiberConfig';
    
  31. import ReactSharedInternals from 'shared/ReactSharedInternals';
    
  32. import {
    
  33.   enableDebugTracing,
    
  34.   enableSchedulingProfiler,
    
  35.   enableCache,
    
  36.   enableUseRefAccessWarning,
    
  37.   enableLazyContextPropagation,
    
  38.   enableTransitionTracing,
    
  39.   enableUseMemoCacheHook,
    
  40.   enableUseEffectEventHook,
    
  41.   enableLegacyCache,
    
  42.   debugRenderPhaseSideEffectsForStrictMode,
    
  43.   enableAsyncActions,
    
  44.   enableFormActions,
    
  45.   enableUseDeferredValueInitialArg,
    
  46. } from 'shared/ReactFeatureFlags';
    
  47. import {
    
  48.   REACT_CONTEXT_TYPE,
    
  49.   REACT_SERVER_CONTEXT_TYPE,
    
  50.   REACT_MEMO_CACHE_SENTINEL,
    
  51. } from 'shared/ReactSymbols';
    
  52. 
    
  53. import {
    
  54.   NoMode,
    
  55.   ConcurrentMode,
    
  56.   DebugTracingMode,
    
  57.   StrictEffectsMode,
    
  58.   StrictLegacyMode,
    
  59.   NoStrictPassiveEffectsMode,
    
  60. } from './ReactTypeOfMode';
    
  61. import {
    
  62.   NoLane,
    
  63.   SyncLane,
    
  64.   OffscreenLane,
    
  65.   DeferredLane,
    
  66.   NoLanes,
    
  67.   isSubsetOfLanes,
    
  68.   includesBlockingLane,
    
  69.   includesOnlyNonUrgentLanes,
    
  70.   mergeLanes,
    
  71.   removeLanes,
    
  72.   intersectLanes,
    
  73.   isTransitionLane,
    
  74.   markRootEntangled,
    
  75.   includesSomeLane,
    
  76. } from './ReactFiberLane';
    
  77. import {
    
  78.   ContinuousEventPriority,
    
  79.   getCurrentUpdatePriority,
    
  80.   setCurrentUpdatePriority,
    
  81.   higherEventPriority,
    
  82. } from './ReactEventPriorities';
    
  83. import {readContext, checkIfContextChanged} from './ReactFiberNewContext';
    
  84. import {HostRoot, CacheComponent, HostComponent} from './ReactWorkTags';
    
  85. import {
    
  86.   LayoutStatic as LayoutStaticEffect,
    
  87.   Passive as PassiveEffect,
    
  88.   PassiveStatic as PassiveStaticEffect,
    
  89.   StaticMask as StaticMaskEffect,
    
  90.   Update as UpdateEffect,
    
  91.   StoreConsistency,
    
  92.   MountLayoutDev as MountLayoutDevEffect,
    
  93.   MountPassiveDev as MountPassiveDevEffect,
    
  94. } from './ReactFiberFlags';
    
  95. import {
    
  96.   HasEffect as HookHasEffect,
    
  97.   Layout as HookLayout,
    
  98.   Passive as HookPassive,
    
  99.   Insertion as HookInsertion,
    
  100. } from './ReactHookEffectTags';
    
  101. import {
    
  102.   getWorkInProgressRoot,
    
  103.   getWorkInProgressRootRenderLanes,
    
  104.   scheduleUpdateOnFiber,
    
  105.   requestUpdateLane,
    
  106.   requestDeferredLane,
    
  107.   markSkippedUpdateLanes,
    
  108.   isInvalidExecutionContextForEventFunction,
    
  109. } from './ReactFiberWorkLoop';
    
  110. 
    
  111. import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
    
  112. import is from 'shared/objectIs';
    
  113. import isArray from 'shared/isArray';
    
  114. import {
    
  115.   markWorkInProgressReceivedUpdate,
    
  116.   checkIfWorkInProgressReceivedUpdate,
    
  117. } from './ReactFiberBeginWork';
    
  118. import {
    
  119.   getIsHydrating,
    
  120.   tryToClaimNextHydratableFormMarkerInstance,
    
  121. } from './ReactFiberHydrationContext';
    
  122. import {logStateUpdateScheduled} from './DebugTracing';
    
  123. import {
    
  124.   markStateUpdateScheduled,
    
  125.   setIsStrictModeForDevtools,
    
  126. } from './ReactFiberDevToolsHook';
    
  127. import {createCache} from './ReactFiberCacheComponent';
    
  128. import {
    
  129.   createUpdate as createLegacyQueueUpdate,
    
  130.   enqueueUpdate as enqueueLegacyQueueUpdate,
    
  131.   entangleTransitions as entangleLegacyQueueTransitions,
    
  132. } from './ReactFiberClassUpdateQueue';
    
  133. import {
    
  134.   enqueueConcurrentHookUpdate,
    
  135.   enqueueConcurrentHookUpdateAndEagerlyBailout,
    
  136.   enqueueConcurrentRenderForLane,
    
  137. } from './ReactFiberConcurrentUpdates';
    
  138. import {getTreeId} from './ReactFiberTreeContext';
    
  139. import {now} from './Scheduler';
    
  140. import {
    
  141.   trackUsedThenable,
    
  142.   checkIfUseWrappedInTryCatch,
    
  143.   createThenableState,
    
  144. } from './ReactFiberThenable';
    
  145. import type {ThenableState} from './ReactFiberThenable';
    
  146. import type {BatchConfigTransition} from './ReactFiberTracingMarkerComponent';
    
  147. import {
    
  148.   requestAsyncActionContext,
    
  149.   requestSyncActionContext,
    
  150.   peekEntangledActionLane,
    
  151. } from './ReactFiberAsyncAction';
    
  152. import {HostTransitionContext} from './ReactFiberHostContext';
    
  153. import {requestTransitionLane} from './ReactFiberRootScheduler';
    
  154. import {isCurrentTreeHidden} from './ReactFiberHiddenContext';
    
  155. 
    
  156. const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;
    
  157. 
    
  158. export type Update<S, A> = {
    
  159.   lane: Lane,
    
  160.   revertLane: Lane,
    
  161.   action: A,
    
  162.   hasEagerState: boolean,
    
  163.   eagerState: S | null,
    
  164.   next: Update<S, A>,
    
  165. };
    
  166. 
    
  167. export type UpdateQueue<S, A> = {
    
  168.   pending: Update<S, A> | null,
    
  169.   lanes: Lanes,
    
  170.   dispatch: (A => mixed) | null,
    
  171.   lastRenderedReducer: ((S, A) => S) | null,
    
  172.   lastRenderedState: S | null,
    
  173. };
    
  174. 
    
  175. let didWarnAboutMismatchedHooksForComponent;
    
  176. let didWarnUncachedGetSnapshot: void | true;
    
  177. let didWarnAboutUseWrappedInTryCatch;
    
  178. let didWarnAboutAsyncClientComponent;
    
  179. if (__DEV__) {
    
  180.   didWarnAboutMismatchedHooksForComponent = new Set<string | null>();
    
  181.   didWarnAboutUseWrappedInTryCatch = new Set<string | null>();
    
  182.   didWarnAboutAsyncClientComponent = new Set<string | null>();
    
  183. }
    
  184. 
    
  185. export type Hook = {
    
  186.   memoizedState: any,
    
  187.   baseState: any,
    
  188.   baseQueue: Update<any, any> | null,
    
  189.   queue: any,
    
  190.   next: Hook | null,
    
  191. };
    
  192. 
    
  193. // The effect "instance" is a shared object that remains the same for the entire
    
  194. // lifetime of an effect. In Rust terms, a RefCell. We use it to store the
    
  195. // "destroy" function that is returned from an effect, because that is stateful.
    
  196. // The field is `undefined` if the effect is unmounted, or if the effect ran
    
  197. // but is not stateful. We don't explicitly track whether the effect is mounted
    
  198. // or unmounted because that can be inferred by the hiddenness of the fiber in
    
  199. // the tree, i.e. whether there is a hidden Offscreen fiber above it.
    
  200. //
    
  201. // It's unfortunate that this is stored on a separate object, because it adds
    
  202. // more memory per effect instance, but it's conceptually sound. I think there's
    
  203. // likely a better data structure we could use for effects; perhaps just one
    
  204. // array of effect instances per fiber. But I think this is OK for now despite
    
  205. // the additional memory and we can follow up with performance
    
  206. // optimizations later.
    
  207. type EffectInstance = {
    
  208.   destroy: void | (() => void),
    
  209. };
    
  210. 
    
  211. export type Effect = {
    
  212.   tag: HookFlags,
    
  213.   create: () => (() => void) | void,
    
  214.   inst: EffectInstance,
    
  215.   deps: Array<mixed> | null,
    
  216.   next: Effect,
    
  217. };
    
  218. 
    
  219. type StoreInstance<T> = {
    
  220.   value: T,
    
  221.   getSnapshot: () => T,
    
  222. };
    
  223. 
    
  224. type StoreConsistencyCheck<T> = {
    
  225.   value: T,
    
  226.   getSnapshot: () => T,
    
  227. };
    
  228. 
    
  229. type EventFunctionPayload<Args, Return, F: (...Array<Args>) => Return> = {
    
  230.   ref: {
    
  231.     eventFn: F,
    
  232.     impl: F,
    
  233.   },
    
  234.   nextImpl: F,
    
  235. };
    
  236. 
    
  237. export type FunctionComponentUpdateQueue = {
    
  238.   lastEffect: Effect | null,
    
  239.   events: Array<EventFunctionPayload<any, any, any>> | null,
    
  240.   stores: Array<StoreConsistencyCheck<any>> | null,
    
  241.   // NOTE: optional, only set when enableUseMemoCacheHook is enabled
    
  242.   memoCache?: MemoCache | null,
    
  243. };
    
  244. 
    
  245. type BasicStateAction<S> = (S => S) | S;
    
  246. 
    
  247. type Dispatch<A> = A => void;
    
  248. 
    
  249. // These are set right before calling the component.
    
  250. let renderLanes: Lanes = NoLanes;
    
  251. // The work-in-progress fiber. I've named it differently to distinguish it from
    
  252. // the work-in-progress hook.
    
  253. let currentlyRenderingFiber: Fiber = (null: any);
    
  254. 
    
  255. // Hooks are stored as a linked list on the fiber's memoizedState field. The
    
  256. // current hook list is the list that belongs to the current fiber. The
    
  257. // work-in-progress hook list is a new list that will be added to the
    
  258. // work-in-progress fiber.
    
  259. let currentHook: Hook | null = null;
    
  260. let workInProgressHook: Hook | null = null;
    
  261. 
    
  262. // Whether an update was scheduled at any point during the render phase. This
    
  263. // does not get reset if we do another render pass; only when we're completely
    
  264. // finished evaluating this component. This is an optimization so we know
    
  265. // whether we need to clear render phase updates after a throw.
    
  266. let didScheduleRenderPhaseUpdate: boolean = false;
    
  267. // Where an update was scheduled only during the current render pass. This
    
  268. // gets reset after each attempt.
    
  269. // TODO: Maybe there's some way to consolidate this with
    
  270. // `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`.
    
  271. let didScheduleRenderPhaseUpdateDuringThisPass: boolean = false;
    
  272. let shouldDoubleInvokeUserFnsInHooksDEV: boolean = false;
    
  273. // Counts the number of useId hooks in this component.
    
  274. let localIdCounter: number = 0;
    
  275. // Counts number of `use`-d thenables
    
  276. let thenableIndexCounter: number = 0;
    
  277. let thenableState: ThenableState | null = null;
    
  278. 
    
  279. // Used for ids that are generated completely client-side (i.e. not during
    
  280. // hydration). This counter is global, so client ids are not stable across
    
  281. // render attempts.
    
  282. let globalClientIdCounter: number = 0;
    
  283. 
    
  284. const RE_RENDER_LIMIT = 25;
    
  285. 
    
  286. // In DEV, this is the name of the currently executing primitive hook
    
  287. let currentHookNameInDev: ?HookType = null;
    
  288. 
    
  289. // In DEV, this list ensures that hooks are called in the same order between renders.
    
  290. // The list stores the order of hooks used during the initial render (mount).
    
  291. // Subsequent renders (updates) reference this list.
    
  292. let hookTypesDev: Array<HookType> | null = null;
    
  293. let hookTypesUpdateIndexDev: number = -1;
    
  294. 
    
  295. // In DEV, this tracks whether currently rendering component needs to ignore
    
  296. // the dependencies for Hooks that need them (e.g. useEffect or useMemo).
    
  297. // When true, such Hooks will always be "remounted". Only used during hot reload.
    
  298. let ignorePreviousDependencies: boolean = false;
    
  299. 
    
  300. function mountHookTypesDev(): void {
    
  301.   if (__DEV__) {
    
  302.     const hookName = ((currentHookNameInDev: any): HookType);
    
  303. 
    
  304.     if (hookTypesDev === null) {
    
  305.       hookTypesDev = [hookName];
    
  306.     } else {
    
  307.       hookTypesDev.push(hookName);
    
  308.     }
    
  309.   }
    
  310. }
    
  311. 
    
  312. function updateHookTypesDev(): void {
    
  313.   if (__DEV__) {
    
  314.     const hookName = ((currentHookNameInDev: any): HookType);
    
  315. 
    
  316.     if (hookTypesDev !== null) {
    
  317.       hookTypesUpdateIndexDev++;
    
  318.       if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) {
    
  319.         warnOnHookMismatchInDev(hookName);
    
  320.       }
    
  321.     }
    
  322.   }
    
  323. }
    
  324. 
    
  325. function checkDepsAreArrayDev(deps: mixed): void {
    
  326.   if (__DEV__) {
    
  327.     if (deps !== undefined && deps !== null && !isArray(deps)) {
    
  328.       // Verify deps, but only on mount to avoid extra checks.
    
  329.       // It's unlikely their type would change as usually you define them inline.
    
  330.       console.error(
    
  331.         '%s received a final argument that is not an array (instead, received `%s`). When ' +
    
  332.           'specified, the final argument must be an array.',
    
  333.         currentHookNameInDev,
    
  334.         typeof deps,
    
  335.       );
    
  336.     }
    
  337.   }
    
  338. }
    
  339. 
    
  340. function warnOnHookMismatchInDev(currentHookName: HookType): void {
    
  341.   if (__DEV__) {
    
  342.     const componentName = getComponentNameFromFiber(currentlyRenderingFiber);
    
  343.     if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) {
    
  344.       didWarnAboutMismatchedHooksForComponent.add(componentName);
    
  345. 
    
  346.       if (hookTypesDev !== null) {
    
  347.         let table = '';
    
  348. 
    
  349.         const secondColumnStart = 30;
    
  350. 
    
  351.         for (let i = 0; i <= ((hookTypesUpdateIndexDev: any): number); i++) {
    
  352.           const oldHookName = hookTypesDev[i];
    
  353.           const newHookName =
    
  354.             i === ((hookTypesUpdateIndexDev: any): number)
    
  355.               ? currentHookName
    
  356.               : oldHookName;
    
  357. 
    
  358.           let row = `${i + 1}. ${oldHookName}`;
    
  359. 
    
  360.           // Extra space so second column lines up
    
  361.           // lol @ IE not supporting String#repeat
    
  362.           while (row.length < secondColumnStart) {
    
  363.             row += ' ';
    
  364.           }
    
  365. 
    
  366.           row += newHookName + '\n';
    
  367. 
    
  368.           table += row;
    
  369.         }
    
  370. 
    
  371.         console.error(
    
  372.           'React has detected a change in the order of Hooks called by %s. ' +
    
  373.             'This will lead to bugs and errors if not fixed. ' +
    
  374.             'For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks\n\n' +
    
  375.             '   Previous render            Next render\n' +
    
  376.             '   ------------------------------------------------------\n' +
    
  377.             '%s' +
    
  378.             '   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n',
    
  379.           componentName,
    
  380.           table,
    
  381.         );
    
  382.       }
    
  383.     }
    
  384.   }
    
  385. }
    
  386. 
    
  387. function warnIfAsyncClientComponent(
    
  388.   Component: Function,
    
  389.   componentDoesIncludeHooks: boolean,
    
  390. ) {
    
  391.   if (__DEV__) {
    
  392.     // This dev-only check only works for detecting native async functions,
    
  393.     // not transpiled ones. There's also a prod check that we use to prevent
    
  394.     // async client components from crashing the app; the prod one works even
    
  395.     // for transpiled async functions. Neither mechanism is completely
    
  396.     // bulletproof but together they cover the most common cases.
    
  397.     const isAsyncFunction =
    
  398.       // $FlowIgnore[method-unbinding]
    
  399.       Object.prototype.toString.call(Component) === '[object AsyncFunction]';
    
  400.     if (isAsyncFunction) {
    
  401.       // Encountered an async Client Component. This is not yet supported,
    
  402.       // except in certain constrained cases, like during a route navigation.
    
  403.       const componentName = getComponentNameFromFiber(currentlyRenderingFiber);
    
  404.       if (!didWarnAboutAsyncClientComponent.has(componentName)) {
    
  405.         didWarnAboutAsyncClientComponent.add(componentName);
    
  406. 
    
  407.         // Check if this is a sync update. We use the "root" render lanes here
    
  408.         // because the "subtree" render lanes may include additional entangled
    
  409.         // lanes related to revealing previously hidden content.
    
  410.         const root = getWorkInProgressRoot();
    
  411.         const rootRenderLanes = getWorkInProgressRootRenderLanes();
    
  412.         if (root !== null && includesBlockingLane(root, rootRenderLanes)) {
    
  413.           console.error(
    
  414.             'async/await is not yet supported in Client Components, only ' +
    
  415.               'Server Components. This error is often caused by accidentally ' +
    
  416.               "adding `'use client'` to a module that was originally written " +
    
  417.               'for the server.',
    
  418.           );
    
  419.         } else {
    
  420.           // This is a concurrent (Transition, Retry, etc) render. We don't
    
  421.           // warn in these cases.
    
  422.           //
    
  423.           // However, Async Components are forbidden to include hooks, even
    
  424.           // during a transition, so let's check for that here.
    
  425.           //
    
  426.           // TODO: Add a corresponding warning to Server Components runtime.
    
  427.           if (componentDoesIncludeHooks) {
    
  428.             console.error(
    
  429.               'Hooks are not supported inside an async component. This ' +
    
  430.                 "error is often caused by accidentally adding `'use client'` " +
    
  431.                 'to a module that was originally written for the server.',
    
  432.             );
    
  433.           }
    
  434.         }
    
  435.       }
    
  436.     }
    
  437.   }
    
  438. }
    
  439. 
    
  440. function throwInvalidHookError() {
    
  441.   throw new Error(
    
  442.     'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
    
  443.       ' one of the following reasons:\n' +
    
  444.       '1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
    
  445.       '2. You might be breaking the Rules of Hooks\n' +
    
  446.       '3. You might have more than one copy of React in the same app\n' +
    
  447.       'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.',
    
  448.   );
    
  449. }
    
  450. 
    
  451. function areHookInputsEqual(
    
  452.   nextDeps: Array<mixed>,
    
  453.   prevDeps: Array<mixed> | null,
    
  454. ): boolean {
    
  455.   if (__DEV__) {
    
  456.     if (ignorePreviousDependencies) {
    
  457.       // Only true when this component is being hot reloaded.
    
  458.       return false;
    
  459.     }
    
  460.   }
    
  461. 
    
  462.   if (prevDeps === null) {
    
  463.     if (__DEV__) {
    
  464.       console.error(
    
  465.         '%s received a final argument during this render, but not during ' +
    
  466.           'the previous render. Even though the final argument is optional, ' +
    
  467.           'its type cannot change between renders.',
    
  468.         currentHookNameInDev,
    
  469.       );
    
  470.     }
    
  471.     return false;
    
  472.   }
    
  473. 
    
  474.   if (__DEV__) {
    
  475.     // Don't bother comparing lengths in prod because these arrays should be
    
  476.     // passed inline.
    
  477.     if (nextDeps.length !== prevDeps.length) {
    
  478.       console.error(
    
  479.         'The final argument passed to %s changed size between renders. The ' +
    
  480.           'order and size of this array must remain constant.\n\n' +
    
  481.           'Previous: %s\n' +
    
  482.           'Incoming: %s',
    
  483.         currentHookNameInDev,
    
  484.         `[${prevDeps.join(', ')}]`,
    
  485.         `[${nextDeps.join(', ')}]`,
    
  486.       );
    
  487.     }
    
  488.   }
    
  489.   // $FlowFixMe[incompatible-use] found when upgrading Flow
    
  490.   for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) {
    
  491.     // $FlowFixMe[incompatible-use] found when upgrading Flow
    
  492.     if (is(nextDeps[i], prevDeps[i])) {
    
  493.       continue;
    
  494.     }
    
  495.     return false;
    
  496.   }
    
  497.   return true;
    
  498. }
    
  499. 
    
  500. export function renderWithHooks<Props, SecondArg>(
    
  501.   current: Fiber | null,
    
  502.   workInProgress: Fiber,
    
  503.   Component: (p: Props, arg: SecondArg) => any,
    
  504.   props: Props,
    
  505.   secondArg: SecondArg,
    
  506.   nextRenderLanes: Lanes,
    
  507. ): any {
    
  508.   renderLanes = nextRenderLanes;
    
  509.   currentlyRenderingFiber = workInProgress;
    
  510. 
    
  511.   if (__DEV__) {
    
  512.     hookTypesDev =
    
  513.       current !== null
    
  514.         ? ((current._debugHookTypes: any): Array<HookType>)
    
  515.         : null;
    
  516.     hookTypesUpdateIndexDev = -1;
    
  517.     // Used for hot reloading:
    
  518.     ignorePreviousDependencies =
    
  519.       current !== null && current.type !== workInProgress.type;
    
  520.   }
    
  521. 
    
  522.   workInProgress.memoizedState = null;
    
  523.   workInProgress.updateQueue = null;
    
  524.   workInProgress.lanes = NoLanes;
    
  525. 
    
  526.   // The following should have already been reset
    
  527.   // currentHook = null;
    
  528.   // workInProgressHook = null;
    
  529. 
    
  530.   // didScheduleRenderPhaseUpdate = false;
    
  531.   // localIdCounter = 0;
    
  532.   // thenableIndexCounter = 0;
    
  533.   // thenableState = null;
    
  534. 
    
  535.   // TODO Warn if no hooks are used at all during mount, then some are used during update.
    
  536.   // Currently we will identify the update render as a mount because memoizedState === null.
    
  537.   // This is tricky because it's valid for certain types of components (e.g. React.lazy)
    
  538. 
    
  539.   // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used.
    
  540.   // Non-stateful hooks (e.g. context) don't get added to memoizedState,
    
  541.   // so memoizedState would be null during updates and mounts.
    
  542.   if (__DEV__) {
    
  543.     if (current !== null && current.memoizedState !== null) {
    
  544.       ReactCurrentDispatcher.current = HooksDispatcherOnUpdateInDEV;
    
  545.     } else if (hookTypesDev !== null) {
    
  546.       // This dispatcher handles an edge case where a component is updating,
    
  547.       // but no stateful hooks have been used.
    
  548.       // We want to match the production code behavior (which will use HooksDispatcherOnMount),
    
  549.       // but with the extra DEV validation to ensure hooks ordering hasn't changed.
    
  550.       // This dispatcher does that.
    
  551.       ReactCurrentDispatcher.current = HooksDispatcherOnMountWithHookTypesInDEV;
    
  552.     } else {
    
  553.       ReactCurrentDispatcher.current = HooksDispatcherOnMountInDEV;
    
  554.     }
    
  555.   } else {
    
  556.     ReactCurrentDispatcher.current =
    
  557.       current === null || current.memoizedState === null
    
  558.         ? HooksDispatcherOnMount
    
  559.         : HooksDispatcherOnUpdate;
    
  560.   }
    
  561. 
    
  562.   // In Strict Mode, during development, user functions are double invoked to
    
  563.   // help detect side effects. The logic for how this is implemented for in
    
  564.   // hook components is a bit complex so let's break it down.
    
  565.   //
    
  566.   // We will invoke the entire component function twice. However, during the
    
  567.   // second invocation of the component, the hook state from the first
    
  568.   // invocation will be reused. That means things like `useMemo` functions won't
    
  569.   // run again, because the deps will match and the memoized result will
    
  570.   // be reused.
    
  571.   //
    
  572.   // We want memoized functions to run twice, too, so account for this, user
    
  573.   // functions are double invoked during the *first* invocation of the component
    
  574.   // function, and are *not* double invoked during the second incovation:
    
  575.   //
    
  576.   // - First execution of component function: user functions are double invoked
    
  577.   // - Second execution of component function (in Strict Mode, during
    
  578.   //   development): user functions are not double invoked.
    
  579.   //
    
  580.   // This is intentional for a few reasons; most importantly, it's because of
    
  581.   // how `use` works when something suspends: it reuses the promise that was
    
  582.   // passed during the first attempt. This is itself a form of memoization.
    
  583.   // We need to be able to memoize the reactive inputs to the `use` call using
    
  584.   // a hook (i.e. `useMemo`), which means, the reactive inputs to `use` must
    
  585.   // come from the same component invocation as the output.
    
  586.   //
    
  587.   // There are plenty of tests to ensure this behavior is correct.
    
  588.   const shouldDoubleRenderDEV =
    
  589.     __DEV__ &&
    
  590.     debugRenderPhaseSideEffectsForStrictMode &&
    
  591.     (workInProgress.mode & StrictLegacyMode) !== NoMode;
    
  592. 
    
  593.   shouldDoubleInvokeUserFnsInHooksDEV = shouldDoubleRenderDEV;
    
  594.   let children = Component(props, secondArg);
    
  595.   shouldDoubleInvokeUserFnsInHooksDEV = false;
    
  596. 
    
  597.   // Check if there was a render phase update
    
  598.   if (didScheduleRenderPhaseUpdateDuringThisPass) {
    
  599.     // Keep rendering until the component stabilizes (there are no more render
    
  600.     // phase updates).
    
  601.     children = renderWithHooksAgain(
    
  602.       workInProgress,
    
  603.       Component,
    
  604.       props,
    
  605.       secondArg,
    
  606.     );
    
  607.   }
    
  608. 
    
  609.   if (shouldDoubleRenderDEV) {
    
  610.     // In development, components are invoked twice to help detect side effects.
    
  611.     setIsStrictModeForDevtools(true);
    
  612.     try {
    
  613.       children = renderWithHooksAgain(
    
  614.         workInProgress,
    
  615.         Component,
    
  616.         props,
    
  617.         secondArg,
    
  618.       );
    
  619.     } finally {
    
  620.       setIsStrictModeForDevtools(false);
    
  621.     }
    
  622.   }
    
  623. 
    
  624.   finishRenderingHooks(current, workInProgress, Component);
    
  625. 
    
  626.   return children;
    
  627. }
    
  628. 
    
  629. function finishRenderingHooks<Props, SecondArg>(
    
  630.   current: Fiber | null,
    
  631.   workInProgress: Fiber,
    
  632.   Component: (p: Props, arg: SecondArg) => any,
    
  633. ): void {
    
  634.   if (__DEV__) {
    
  635.     workInProgress._debugHookTypes = hookTypesDev;
    
  636. 
    
  637.     const componentDoesIncludeHooks =
    
  638.       workInProgressHook !== null || thenableIndexCounter !== 0;
    
  639.     warnIfAsyncClientComponent(Component, componentDoesIncludeHooks);
    
  640.   }
    
  641. 
    
  642.   // We can assume the previous dispatcher is always this one, since we set it
    
  643.   // at the beginning of the render phase and there's no re-entrance.
    
  644.   ReactCurrentDispatcher.current = ContextOnlyDispatcher;
    
  645. 
    
  646.   // This check uses currentHook so that it works the same in DEV and prod bundles.
    
  647.   // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles.
    
  648.   const didRenderTooFewHooks =
    
  649.     currentHook !== null && currentHook.next !== null;
    
  650. 
    
  651.   renderLanes = NoLanes;
    
  652.   currentlyRenderingFiber = (null: any);
    
  653. 
    
  654.   currentHook = null;
    
  655.   workInProgressHook = null;
    
  656. 
    
  657.   if (__DEV__) {
    
  658.     currentHookNameInDev = null;
    
  659.     hookTypesDev = null;
    
  660.     hookTypesUpdateIndexDev = -1;
    
  661. 
    
  662.     // Confirm that a static flag was not added or removed since the last
    
  663.     // render. If this fires, it suggests that we incorrectly reset the static
    
  664.     // flags in some other part of the codebase. This has happened before, for
    
  665.     // example, in the SuspenseList implementation.
    
  666.     if (
    
  667.       current !== null &&
    
  668.       (current.flags & StaticMaskEffect) !==
    
  669.         (workInProgress.flags & StaticMaskEffect) &&
    
  670.       // Disable this warning in legacy mode, because legacy Suspense is weird
    
  671.       // and creates false positives. To make this work in legacy mode, we'd
    
  672.       // need to mark fibers that commit in an incomplete state, somehow. For
    
  673.       // now I'll disable the warning that most of the bugs that would trigger
    
  674.       // it are either exclusive to concurrent mode or exist in both.
    
  675.       (current.mode & ConcurrentMode) !== NoMode
    
  676.     ) {
    
  677.       console.error(
    
  678.         'Internal React error: Expected static flag was missing. Please ' +
    
  679.           'notify the React team.',
    
  680.       );
    
  681.     }
    
  682.   }
    
  683. 
    
  684.   didScheduleRenderPhaseUpdate = false;
    
  685.   // This is reset by checkDidRenderIdHook
    
  686.   // localIdCounter = 0;
    
  687. 
    
  688.   thenableIndexCounter = 0;
    
  689.   thenableState = null;
    
  690. 
    
  691.   if (didRenderTooFewHooks) {
    
  692.     throw new Error(
    
  693.       'Rendered fewer hooks than expected. This may be caused by an accidental ' +
    
  694.         'early return statement.',
    
  695.     );
    
  696.   }
    
  697. 
    
  698.   if (enableLazyContextPropagation) {
    
  699.     if (current !== null) {
    
  700.       if (!checkIfWorkInProgressReceivedUpdate()) {
    
  701.         // If there were no changes to props or state, we need to check if there
    
  702.         // was a context change. We didn't already do this because there's no
    
  703.         // 1:1 correspondence between dependencies and hooks. Although, because
    
  704.         // there almost always is in the common case (`readContext` is an
    
  705.         // internal API), we could compare in there. OTOH, we only hit this case
    
  706.         // if everything else bails out, so on the whole it might be better to
    
  707.         // keep the comparison out of the common path.
    
  708.         const currentDependencies = current.dependencies;
    
  709.         if (
    
  710.           currentDependencies !== null &&
    
  711.           checkIfContextChanged(currentDependencies)
    
  712.         ) {
    
  713.           markWorkInProgressReceivedUpdate();
    
  714.         }
    
  715.       }
    
  716.     }
    
  717.   }
    
  718. 
    
  719.   if (__DEV__) {
    
  720.     if (checkIfUseWrappedInTryCatch()) {
    
  721.       const componentName =
    
  722.         getComponentNameFromFiber(workInProgress) || 'Unknown';
    
  723.       if (
    
  724.         !didWarnAboutUseWrappedInTryCatch.has(componentName) &&
    
  725.         // This warning also fires if you suspend with `use` inside an
    
  726.         // async component. Since we warn for that above, we'll silence this
    
  727.         // second warning by checking here.
    
  728.         !didWarnAboutAsyncClientComponent.has(componentName)
    
  729.       ) {
    
  730.         didWarnAboutUseWrappedInTryCatch.add(componentName);
    
  731.         console.error(
    
  732.           '`use` was called from inside a try/catch block. This is not allowed ' +
    
  733.             'and can lead to unexpected behavior. To handle errors triggered ' +
    
  734.             'by `use`, wrap your component in a error boundary.',
    
  735.         );
    
  736.       }
    
  737.     }
    
  738.   }
    
  739. }
    
  740. 
    
  741. export function replaySuspendedComponentWithHooks<Props, SecondArg>(
    
  742.   current: Fiber | null,
    
  743.   workInProgress: Fiber,
    
  744.   Component: (p: Props, arg: SecondArg) => any,
    
  745.   props: Props,
    
  746.   secondArg: SecondArg,
    
  747. ): any {
    
  748.   // This function is used to replay a component that previously suspended,
    
  749.   // after its data resolves.
    
  750.   //
    
  751.   // It's a simplified version of renderWithHooks, but it doesn't need to do
    
  752.   // most of the set up work because they weren't reset when we suspended; they
    
  753.   // only get reset when the component either completes (finishRenderingHooks)
    
  754.   // or unwinds (resetHooksOnUnwind).
    
  755.   if (__DEV__) {
    
  756.     hookTypesUpdateIndexDev = -1;
    
  757.     // Used for hot reloading:
    
  758.     ignorePreviousDependencies =
    
  759.       current !== null && current.type !== workInProgress.type;
    
  760.   }
    
  761.   const children = renderWithHooksAgain(
    
  762.     workInProgress,
    
  763.     Component,
    
  764.     props,
    
  765.     secondArg,
    
  766.   );
    
  767.   finishRenderingHooks(current, workInProgress, Component);
    
  768.   return children;
    
  769. }
    
  770. 
    
  771. function renderWithHooksAgain<Props, SecondArg>(
    
  772.   workInProgress: Fiber,
    
  773.   Component: (p: Props, arg: SecondArg) => any,
    
  774.   props: Props,
    
  775.   secondArg: SecondArg,
    
  776. ): any {
    
  777.   // This is used to perform another render pass. It's used when setState is
    
  778.   // called during render, and for double invoking components in Strict Mode
    
  779.   // during development.
    
  780.   //
    
  781.   // The state from the previous pass is reused whenever possible. So, state
    
  782.   // updates that were already processed are not processed again, and memoized
    
  783.   // functions (`useMemo`) are not invoked again.
    
  784.   //
    
  785.   // Keep rendering in a loop for as long as render phase updates continue to
    
  786.   // be scheduled. Use a counter to prevent infinite loops.
    
  787. 
    
  788.   currentlyRenderingFiber = workInProgress;
    
  789. 
    
  790.   let numberOfReRenders: number = 0;
    
  791.   let children;
    
  792.   do {
    
  793.     if (didScheduleRenderPhaseUpdateDuringThisPass) {
    
  794.       // It's possible that a use() value depended on a state that was updated in
    
  795.       // this rerender, so we need to watch for different thenables this time.
    
  796.       thenableState = null;
    
  797.     }
    
  798.     thenableIndexCounter = 0;
    
  799.     didScheduleRenderPhaseUpdateDuringThisPass = false;
    
  800. 
    
  801.     if (numberOfReRenders >= RE_RENDER_LIMIT) {
    
  802.       throw new Error(
    
  803.         'Too many re-renders. React limits the number of renders to prevent ' +
    
  804.           'an infinite loop.',
    
  805.       );
    
  806.     }
    
  807. 
    
  808.     numberOfReRenders += 1;
    
  809.     if (__DEV__) {
    
  810.       // Even when hot reloading, allow dependencies to stabilize
    
  811.       // after first render to prevent infinite render phase updates.
    
  812.       ignorePreviousDependencies = false;
    
  813.     }
    
  814. 
    
  815.     // Start over from the beginning of the list
    
  816.     currentHook = null;
    
  817.     workInProgressHook = null;
    
  818. 
    
  819.     workInProgress.updateQueue = null;
    
  820. 
    
  821.     if (__DEV__) {
    
  822.       // Also validate hook order for cascading updates.
    
  823.       hookTypesUpdateIndexDev = -1;
    
  824.     }
    
  825. 
    
  826.     ReactCurrentDispatcher.current = __DEV__
    
  827.       ? HooksDispatcherOnRerenderInDEV
    
  828.       : HooksDispatcherOnRerender;
    
  829. 
    
  830.     children = Component(props, secondArg);
    
  831.   } while (didScheduleRenderPhaseUpdateDuringThisPass);
    
  832.   return children;
    
  833. }
    
  834. 
    
  835. export function renderTransitionAwareHostComponentWithHooks(
    
  836.   current: Fiber | null,
    
  837.   workInProgress: Fiber,
    
  838.   lanes: Lanes,
    
  839. ): TransitionStatus {
    
  840.   if (!(enableFormActions && enableAsyncActions)) {
    
  841.     throw new Error('Not implemented.');
    
  842.   }
    
  843.   return renderWithHooks(
    
  844.     current,
    
  845.     workInProgress,
    
  846.     TransitionAwareHostComponent,
    
  847.     null,
    
  848.     null,
    
  849.     lanes,
    
  850.   );
    
  851. }
    
  852. 
    
  853. export function TransitionAwareHostComponent(): TransitionStatus {
    
  854.   if (!(enableFormActions && enableAsyncActions)) {
    
  855.     throw new Error('Not implemented.');
    
  856.   }
    
  857.   const dispatcher = ReactCurrentDispatcher.current;
    
  858.   const [maybeThenable] = dispatcher.useState();
    
  859.   if (typeof maybeThenable.then === 'function') {
    
  860.     const thenable: Thenable<TransitionStatus> = (maybeThenable: any);
    
  861.     return useThenable(thenable);
    
  862.   } else {
    
  863.     const status: TransitionStatus = maybeThenable;
    
  864.     return status;
    
  865.   }
    
  866. }
    
  867. 
    
  868. export function checkDidRenderIdHook(): boolean {
    
  869.   // This should be called immediately after every renderWithHooks call.
    
  870.   // Conceptually, it's part of the return value of renderWithHooks; it's only a
    
  871.   // separate function to avoid using an array tuple.
    
  872.   const didRenderIdHook = localIdCounter !== 0;
    
  873.   localIdCounter = 0;
    
  874.   return didRenderIdHook;
    
  875. }
    
  876. 
    
  877. export function bailoutHooks(
    
  878.   current: Fiber,
    
  879.   workInProgress: Fiber,
    
  880.   lanes: Lanes,
    
  881. ): void {
    
  882.   workInProgress.updateQueue = current.updateQueue;
    
  883.   // TODO: Don't need to reset the flags here, because they're reset in the
    
  884.   // complete phase (bubbleProperties).
    
  885.   if (__DEV__ && (workInProgress.mode & StrictEffectsMode) !== NoMode) {
    
  886.     workInProgress.flags &= ~(
    
  887.       MountPassiveDevEffect |
    
  888.       MountLayoutDevEffect |
    
  889.       PassiveEffect |
    
  890.       UpdateEffect
    
  891.     );
    
  892.   } else {
    
  893.     workInProgress.flags &= ~(PassiveEffect | UpdateEffect);
    
  894.   }
    
  895.   current.lanes = removeLanes(current.lanes, lanes);
    
  896. }
    
  897. 
    
  898. export function resetHooksAfterThrow(): void {
    
  899.   // This is called immediaetly after a throw. It shouldn't reset the entire
    
  900.   // module state, because the work loop might decide to replay the component
    
  901.   // again without rewinding.
    
  902.   //
    
  903.   // It should only reset things like the current dispatcher, to prevent hooks
    
  904.   // from being called outside of a component.
    
  905.   currentlyRenderingFiber = (null: any);
    
  906. 
    
  907.   // We can assume the previous dispatcher is always this one, since we set it
    
  908.   // at the beginning of the render phase and there's no re-entrance.
    
  909.   ReactCurrentDispatcher.current = ContextOnlyDispatcher;
    
  910. }
    
  911. 
    
  912. export function resetHooksOnUnwind(workInProgress: Fiber): void {
    
  913.   if (didScheduleRenderPhaseUpdate) {
    
  914.     // There were render phase updates. These are only valid for this render
    
  915.     // phase, which we are now aborting. Remove the updates from the queues so
    
  916.     // they do not persist to the next render. Do not remove updates from hooks
    
  917.     // that weren't processed.
    
  918.     //
    
  919.     // Only reset the updates from the queue if it has a clone. If it does
    
  920.     // not have a clone, that means it wasn't processed, and the updates were
    
  921.     // scheduled before we entered the render phase.
    
  922.     let hook: Hook | null = workInProgress.memoizedState;
    
  923.     while (hook !== null) {
    
  924.       const queue = hook.queue;
    
  925.       if (queue !== null) {
    
  926.         queue.pending = null;
    
  927.       }
    
  928.       hook = hook.next;
    
  929.     }
    
  930.     didScheduleRenderPhaseUpdate = false;
    
  931.   }
    
  932. 
    
  933.   renderLanes = NoLanes;
    
  934.   currentlyRenderingFiber = (null: any);
    
  935. 
    
  936.   currentHook = null;
    
  937.   workInProgressHook = null;
    
  938. 
    
  939.   if (__DEV__) {
    
  940.     hookTypesDev = null;
    
  941.     hookTypesUpdateIndexDev = -1;
    
  942. 
    
  943.     currentHookNameInDev = null;
    
  944.   }
    
  945. 
    
  946.   didScheduleRenderPhaseUpdateDuringThisPass = false;
    
  947.   localIdCounter = 0;
    
  948.   thenableIndexCounter = 0;
    
  949.   thenableState = null;
    
  950. }
    
  951. 
    
  952. function mountWorkInProgressHook(): Hook {
    
  953.   const hook: Hook = {
    
  954.     memoizedState: null,
    
  955. 
    
  956.     baseState: null,
    
  957.     baseQueue: null,
    
  958.     queue: null,
    
  959. 
    
  960.     next: null,
    
  961.   };
    
  962. 
    
  963.   if (workInProgressHook === null) {
    
  964.     // This is the first hook in the list
    
  965.     currentlyRenderingFiber.memoizedState = workInProgressHook = hook;
    
  966.   } else {
    
  967.     // Append to the end of the list
    
  968.     workInProgressHook = workInProgressHook.next = hook;
    
  969.   }
    
  970.   return workInProgressHook;
    
  971. }
    
  972. 
    
  973. function updateWorkInProgressHook(): Hook {
    
  974.   // This function is used both for updates and for re-renders triggered by a
    
  975.   // render phase update. It assumes there is either a current hook we can
    
  976.   // clone, or a work-in-progress hook from a previous render pass that we can
    
  977.   // use as a base.
    
  978.   let nextCurrentHook: null | Hook;
    
  979.   if (currentHook === null) {
    
  980.     const current = currentlyRenderingFiber.alternate;
    
  981.     if (current !== null) {
    
  982.       nextCurrentHook = current.memoizedState;
    
  983.     } else {
    
  984.       nextCurrentHook = null;
    
  985.     }
    
  986.   } else {
    
  987.     nextCurrentHook = currentHook.next;
    
  988.   }
    
  989. 
    
  990.   let nextWorkInProgressHook: null | Hook;
    
  991.   if (workInProgressHook === null) {
    
  992.     nextWorkInProgressHook = currentlyRenderingFiber.memoizedState;
    
  993.   } else {
    
  994.     nextWorkInProgressHook = workInProgressHook.next;
    
  995.   }
    
  996. 
    
  997.   if (nextWorkInProgressHook !== null) {
    
  998.     // There's already a work-in-progress. Reuse it.
    
  999.     workInProgressHook = nextWorkInProgressHook;
    
  1000.     nextWorkInProgressHook = workInProgressHook.next;
    
  1001. 
    
  1002.     currentHook = nextCurrentHook;
    
  1003.   } else {
    
  1004.     // Clone from the current hook.
    
  1005. 
    
  1006.     if (nextCurrentHook === null) {
    
  1007.       const currentFiber = currentlyRenderingFiber.alternate;
    
  1008.       if (currentFiber === null) {
    
  1009.         // This is the initial render. This branch is reached when the component
    
  1010.         // suspends, resumes, then renders an additional hook.
    
  1011.         // Should never be reached because we should switch to the mount dispatcher first.
    
  1012.         throw new Error(
    
  1013.           'Update hook called on initial render. This is likely a bug in React. Please file an issue.',
    
  1014.         );
    
  1015.       } else {
    
  1016.         // This is an update. We should always have a current hook.
    
  1017.         throw new Error('Rendered more hooks than during the previous render.');
    
  1018.       }
    
  1019.     }
    
  1020. 
    
  1021.     currentHook = nextCurrentHook;
    
  1022. 
    
  1023.     const newHook: Hook = {
    
  1024.       memoizedState: currentHook.memoizedState,
    
  1025. 
    
  1026.       baseState: currentHook.baseState,
    
  1027.       baseQueue: currentHook.baseQueue,
    
  1028.       queue: currentHook.queue,
    
  1029. 
    
  1030.       next: null,
    
  1031.     };
    
  1032. 
    
  1033.     if (workInProgressHook === null) {
    
  1034.       // This is the first hook in the list.
    
  1035.       currentlyRenderingFiber.memoizedState = workInProgressHook = newHook;
    
  1036.     } else {
    
  1037.       // Append to the end of the list.
    
  1038.       workInProgressHook = workInProgressHook.next = newHook;
    
  1039.     }
    
  1040.   }
    
  1041.   return workInProgressHook;
    
  1042. }
    
  1043. 
    
  1044. // NOTE: defining two versions of this function to avoid size impact when this feature is disabled.
    
  1045. // Previously this function was inlined, the additional `memoCache` property makes it not inlined.
    
  1046. let createFunctionComponentUpdateQueue: () => FunctionComponentUpdateQueue;
    
  1047. if (enableUseMemoCacheHook) {
    
  1048.   createFunctionComponentUpdateQueue = () => {
    
  1049.     return {
    
  1050.       lastEffect: null,
    
  1051.       events: null,
    
  1052.       stores: null,
    
  1053.       memoCache: null,
    
  1054.     };
    
  1055.   };
    
  1056. } else {
    
  1057.   createFunctionComponentUpdateQueue = () => {
    
  1058.     return {
    
  1059.       lastEffect: null,
    
  1060.       events: null,
    
  1061.       stores: null,
    
  1062.     };
    
  1063.   };
    
  1064. }
    
  1065. 
    
  1066. function useThenable<T>(thenable: Thenable<T>): T {
    
  1067.   // Track the position of the thenable within this fiber.
    
  1068.   const index = thenableIndexCounter;
    
  1069.   thenableIndexCounter += 1;
    
  1070.   if (thenableState === null) {
    
  1071.     thenableState = createThenableState();
    
  1072.   }
    
  1073.   const result = trackUsedThenable(thenableState, thenable, index);
    
  1074.   if (
    
  1075.     currentlyRenderingFiber.alternate === null &&
    
  1076.     (workInProgressHook === null
    
  1077.       ? currentlyRenderingFiber.memoizedState === null
    
  1078.       : workInProgressHook.next === null)
    
  1079.   ) {
    
  1080.     // Initial render, and either this is the first time the component is
    
  1081.     // called, or there were no Hooks called after this use() the previous
    
  1082.     // time (perhaps because it threw). Subsequent Hook calls should use the
    
  1083.     // mount dispatcher.
    
  1084.     if (__DEV__) {
    
  1085.       ReactCurrentDispatcher.current = HooksDispatcherOnMountInDEV;
    
  1086.     } else {
    
  1087.       ReactCurrentDispatcher.current = HooksDispatcherOnMount;
    
  1088.     }
    
  1089.   }
    
  1090.   return result;
    
  1091. }
    
  1092. 
    
  1093. function use<T>(usable: Usable<T>): T {
    
  1094.   if (usable !== null && typeof usable === 'object') {
    
  1095.     // $FlowFixMe[method-unbinding]
    
  1096.     if (typeof usable.then === 'function') {
    
  1097.       // This is a thenable.
    
  1098.       const thenable: Thenable<T> = (usable: any);
    
  1099.       return useThenable(thenable);
    
  1100.     } else if (
    
  1101.       usable.$$typeof === REACT_CONTEXT_TYPE ||
    
  1102.       usable.$$typeof === REACT_SERVER_CONTEXT_TYPE
    
  1103.     ) {
    
  1104.       const context: ReactContext<T> = (usable: any);
    
  1105.       return readContext(context);
    
  1106.     }
    
  1107.   }
    
  1108. 
    
  1109.   // eslint-disable-next-line react-internal/safe-string-coercion
    
  1110.   throw new Error('An unsupported type was passed to use(): ' + String(usable));
    
  1111. }
    
  1112. 
    
  1113. function useMemoCache(size: number): Array<any> {
    
  1114.   let memoCache = null;
    
  1115.   // Fast-path, load memo cache from wip fiber if already prepared
    
  1116.   let updateQueue: FunctionComponentUpdateQueue | null =
    
  1117.     (currentlyRenderingFiber.updateQueue: any);
    
  1118.   if (updateQueue !== null) {
    
  1119.     memoCache = updateQueue.memoCache;
    
  1120.   }
    
  1121.   // Otherwise clone from the current fiber
    
  1122.   if (memoCache == null) {
    
  1123.     const current: Fiber | null = currentlyRenderingFiber.alternate;
    
  1124.     if (current !== null) {
    
  1125.       const currentUpdateQueue: FunctionComponentUpdateQueue | null =
    
  1126.         (current.updateQueue: any);
    
  1127.       if (currentUpdateQueue !== null) {
    
  1128.         const currentMemoCache: ?MemoCache = currentUpdateQueue.memoCache;
    
  1129.         if (currentMemoCache != null) {
    
  1130.           memoCache = {
    
  1131.             data: currentMemoCache.data.map(array => array.slice()),
    
  1132.             index: 0,
    
  1133.           };
    
  1134.         }
    
  1135.       }
    
  1136.     }
    
  1137.   }
    
  1138.   // Finally fall back to allocating a fresh instance of the cache
    
  1139.   if (memoCache == null) {
    
  1140.     memoCache = {
    
  1141.       data: [],
    
  1142.       index: 0,
    
  1143.     };
    
  1144.   }
    
  1145.   if (updateQueue === null) {
    
  1146.     updateQueue = createFunctionComponentUpdateQueue();
    
  1147.     currentlyRenderingFiber.updateQueue = updateQueue;
    
  1148.   }
    
  1149.   updateQueue.memoCache = memoCache;
    
  1150. 
    
  1151.   let data = memoCache.data[memoCache.index];
    
  1152.   if (data === undefined) {
    
  1153.     data = memoCache.data[memoCache.index] = new Array(size);
    
  1154.     for (let i = 0; i < size; i++) {
    
  1155.       data[i] = REACT_MEMO_CACHE_SENTINEL;
    
  1156.     }
    
  1157.   } else if (data.length !== size) {
    
  1158.     // TODO: consider warning or throwing here
    
  1159.     if (__DEV__) {
    
  1160.       console.error(
    
  1161.         'Expected a constant size argument for each invocation of useMemoCache. ' +
    
  1162.           'The previous cache was allocated with size %s but size %s was requested.',
    
  1163.         data.length,
    
  1164.         size,
    
  1165.       );
    
  1166.     }
    
  1167.   }
    
  1168.   memoCache.index++;
    
  1169.   return data;
    
  1170. }
    
  1171. 
    
  1172. function basicStateReducer<S>(state: S, action: BasicStateAction<S>): S {
    
  1173.   // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types
    
  1174.   return typeof action === 'function' ? action(state) : action;
    
  1175. }
    
  1176. 
    
  1177. function mountReducer<S, I, A>(
    
  1178.   reducer: (S, A) => S,
    
  1179.   initialArg: I,
    
  1180.   init?: I => S,
    
  1181. ): [S, Dispatch<A>] {
    
  1182.   const hook = mountWorkInProgressHook();
    
  1183.   let initialState;
    
  1184.   if (init !== undefined) {
    
  1185.     initialState = init(initialArg);
    
  1186.   } else {
    
  1187.     initialState = ((initialArg: any): S);
    
  1188.   }
    
  1189.   hook.memoizedState = hook.baseState = initialState;
    
  1190.   const queue: UpdateQueue<S, A> = {
    
  1191.     pending: null,
    
  1192.     lanes: NoLanes,
    
  1193.     dispatch: null,
    
  1194.     lastRenderedReducer: reducer,
    
  1195.     lastRenderedState: (initialState: any),
    
  1196.   };
    
  1197.   hook.queue = queue;
    
  1198.   const dispatch: Dispatch<A> = (queue.dispatch = (dispatchReducerAction.bind(
    
  1199.     null,
    
  1200.     currentlyRenderingFiber,
    
  1201.     queue,
    
  1202.   ): any));
    
  1203.   return [hook.memoizedState, dispatch];
    
  1204. }
    
  1205. 
    
  1206. function updateReducer<S, I, A>(
    
  1207.   reducer: (S, A) => S,
    
  1208.   initialArg: I,
    
  1209.   init?: I => S,
    
  1210. ): [S, Dispatch<A>] {
    
  1211.   const hook = updateWorkInProgressHook();
    
  1212.   return updateReducerImpl(hook, ((currentHook: any): Hook), reducer);
    
  1213. }
    
  1214. 
    
  1215. function updateReducerImpl<S, A>(
    
  1216.   hook: Hook,
    
  1217.   current: Hook,
    
  1218.   reducer: (S, A) => S,
    
  1219. ): [S, Dispatch<A>] {
    
  1220.   const queue = hook.queue;
    
  1221. 
    
  1222.   if (queue === null) {
    
  1223.     throw new Error(
    
  1224.       'Should have a queue. This is likely a bug in React. Please file an issue.',
    
  1225.     );
    
  1226.   }
    
  1227. 
    
  1228.   queue.lastRenderedReducer = reducer;
    
  1229. 
    
  1230.   // The last rebase update that is NOT part of the base state.
    
  1231.   let baseQueue = hook.baseQueue;
    
  1232. 
    
  1233.   // The last pending update that hasn't been processed yet.
    
  1234.   const pendingQueue = queue.pending;
    
  1235.   if (pendingQueue !== null) {
    
  1236.     // We have new updates that haven't been processed yet.
    
  1237.     // We'll add them to the base queue.
    
  1238.     if (baseQueue !== null) {
    
  1239.       // Merge the pending queue and the base queue.
    
  1240.       const baseFirst = baseQueue.next;
    
  1241.       const pendingFirst = pendingQueue.next;
    
  1242.       baseQueue.next = pendingFirst;
    
  1243.       pendingQueue.next = baseFirst;
    
  1244.     }
    
  1245.     if (__DEV__) {
    
  1246.       if (current.baseQueue !== baseQueue) {
    
  1247.         // Internal invariant that should never happen, but feasibly could in
    
  1248.         // the future if we implement resuming, or some form of that.
    
  1249.         console.error(
    
  1250.           'Internal error: Expected work-in-progress queue to be a clone. ' +
    
  1251.             'This is a bug in React.',
    
  1252.         );
    
  1253.       }
    
  1254.     }
    
  1255.     current.baseQueue = baseQueue = pendingQueue;
    
  1256.     queue.pending = null;
    
  1257.   }
    
  1258. 
    
  1259.   if (baseQueue !== null) {
    
  1260.     // We have a queue to process.
    
  1261.     const first = baseQueue.next;
    
  1262.     let newState = hook.baseState;
    
  1263. 
    
  1264.     let newBaseState = null;
    
  1265.     let newBaseQueueFirst = null;
    
  1266.     let newBaseQueueLast: Update<S, A> | null = null;
    
  1267.     let update = first;
    
  1268.     do {
    
  1269.       // An extra OffscreenLane bit is added to updates that were made to
    
  1270.       // a hidden tree, so that we can distinguish them from updates that were
    
  1271.       // already there when the tree was hidden.
    
  1272.       const updateLane = removeLanes(update.lane, OffscreenLane);
    
  1273.       const isHiddenUpdate = updateLane !== update.lane;
    
  1274. 
    
  1275.       // Check if this update was made while the tree was hidden. If so, then
    
  1276.       // it's not a "base" update and we should disregard the extra base lanes
    
  1277.       // that were added to renderLanes when we entered the Offscreen tree.
    
  1278.       const shouldSkipUpdate = isHiddenUpdate
    
  1279.         ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane)
    
  1280.         : !isSubsetOfLanes(renderLanes, updateLane);
    
  1281. 
    
  1282.       if (shouldSkipUpdate) {
    
  1283.         // Priority is insufficient. Skip this update. If this is the first
    
  1284.         // skipped update, the previous update/state is the new base
    
  1285.         // update/state.
    
  1286.         const clone: Update<S, A> = {
    
  1287.           lane: updateLane,
    
  1288.           revertLane: update.revertLane,
    
  1289.           action: update.action,
    
  1290.           hasEagerState: update.hasEagerState,
    
  1291.           eagerState: update.eagerState,
    
  1292.           next: (null: any),
    
  1293.         };
    
  1294.         if (newBaseQueueLast === null) {
    
  1295.           newBaseQueueFirst = newBaseQueueLast = clone;
    
  1296.           newBaseState = newState;
    
  1297.         } else {
    
  1298.           newBaseQueueLast = newBaseQueueLast.next = clone;
    
  1299.         }
    
  1300.         // Update the remaining priority in the queue.
    
  1301.         // TODO: Don't need to accumulate this. Instead, we can remove
    
  1302.         // renderLanes from the original lanes.
    
  1303.         currentlyRenderingFiber.lanes = mergeLanes(
    
  1304.           currentlyRenderingFiber.lanes,
    
  1305.           updateLane,
    
  1306.         );
    
  1307.         markSkippedUpdateLanes(updateLane);
    
  1308.       } else {
    
  1309.         // This update does have sufficient priority.
    
  1310. 
    
  1311.         // Check if this is an optimistic update.
    
  1312.         const revertLane = update.revertLane;
    
  1313.         if (!enableAsyncActions || revertLane === NoLane) {
    
  1314.           // This is not an optimistic update, and we're going to apply it now.
    
  1315.           // But, if there were earlier updates that were skipped, we need to
    
  1316.           // leave this update in the queue so it can be rebased later.
    
  1317.           if (newBaseQueueLast !== null) {
    
  1318.             const clone: Update<S, A> = {
    
  1319.               // This update is going to be committed so we never want uncommit
    
  1320.               // it. Using NoLane works because 0 is a subset of all bitmasks, so
    
  1321.               // this will never be skipped by the check above.
    
  1322.               lane: NoLane,
    
  1323.               revertLane: NoLane,
    
  1324.               action: update.action,
    
  1325.               hasEagerState: update.hasEagerState,
    
  1326.               eagerState: update.eagerState,
    
  1327.               next: (null: any),
    
  1328.             };
    
  1329.             newBaseQueueLast = newBaseQueueLast.next = clone;
    
  1330.           }
    
  1331.         } else {
    
  1332.           // This is an optimistic update. If the "revert" priority is
    
  1333.           // sufficient, don't apply the update. Otherwise, apply the update,
    
  1334.           // but leave it in the queue so it can be either reverted or
    
  1335.           // rebased in a subsequent render.
    
  1336.           if (isSubsetOfLanes(renderLanes, revertLane)) {
    
  1337.             // The transition that this optimistic update is associated with
    
  1338.             // has finished. Pretend the update doesn't exist by skipping
    
  1339.             // over it.
    
  1340.             update = update.next;
    
  1341.             continue;
    
  1342.           } else {
    
  1343.             const clone: Update<S, A> = {
    
  1344.               // Once we commit an optimistic update, we shouldn't uncommit it
    
  1345.               // until the transition it is associated with has finished
    
  1346.               // (represented by revertLane). Using NoLane here works because 0
    
  1347.               // is a subset of all bitmasks, so this will never be skipped by
    
  1348.               // the check above.
    
  1349.               lane: NoLane,
    
  1350.               // Reuse the same revertLane so we know when the transition
    
  1351.               // has finished.
    
  1352.               revertLane: update.revertLane,
    
  1353.               action: update.action,
    
  1354.               hasEagerState: update.hasEagerState,
    
  1355.               eagerState: update.eagerState,
    
  1356.               next: (null: any),
    
  1357.             };
    
  1358.             if (newBaseQueueLast === null) {
    
  1359.               newBaseQueueFirst = newBaseQueueLast = clone;
    
  1360.               newBaseState = newState;
    
  1361.             } else {
    
  1362.               newBaseQueueLast = newBaseQueueLast.next = clone;
    
  1363.             }
    
  1364.             // Update the remaining priority in the queue.
    
  1365.             // TODO: Don't need to accumulate this. Instead, we can remove
    
  1366.             // renderLanes from the original lanes.
    
  1367.             currentlyRenderingFiber.lanes = mergeLanes(
    
  1368.               currentlyRenderingFiber.lanes,
    
  1369.               revertLane,
    
  1370.             );
    
  1371.             markSkippedUpdateLanes(revertLane);
    
  1372.           }
    
  1373.         }
    
  1374. 
    
  1375.         // Process this update.
    
  1376.         const action = update.action;
    
  1377.         if (shouldDoubleInvokeUserFnsInHooksDEV) {
    
  1378.           reducer(newState, action);
    
  1379.         }
    
  1380.         if (update.hasEagerState) {
    
  1381.           // If this update is a state update (not a reducer) and was processed eagerly,
    
  1382.           // we can use the eagerly computed state
    
  1383.           newState = ((update.eagerState: any): S);
    
  1384.         } else {
    
  1385.           newState = reducer(newState, action);
    
  1386.         }
    
  1387.       }
    
  1388.       update = update.next;
    
  1389.     } while (update !== null && update !== first);
    
  1390. 
    
  1391.     if (newBaseQueueLast === null) {
    
  1392.       newBaseState = newState;
    
  1393.     } else {
    
  1394.       newBaseQueueLast.next = (newBaseQueueFirst: any);
    
  1395.     }
    
  1396. 
    
  1397.     // Mark that the fiber performed work, but only if the new state is
    
  1398.     // different from the current state.
    
  1399.     if (!is(newState, hook.memoizedState)) {
    
  1400.       markWorkInProgressReceivedUpdate();
    
  1401.     }
    
  1402. 
    
  1403.     hook.memoizedState = newState;
    
  1404.     hook.baseState = newBaseState;
    
  1405.     hook.baseQueue = newBaseQueueLast;
    
  1406. 
    
  1407.     queue.lastRenderedState = newState;
    
  1408.   }
    
  1409. 
    
  1410.   if (baseQueue === null) {
    
  1411.     // `queue.lanes` is used for entangling transitions. We can set it back to
    
  1412.     // zero once the queue is empty.
    
  1413.     queue.lanes = NoLanes;
    
  1414.   }
    
  1415. 
    
  1416.   const dispatch: Dispatch<A> = (queue.dispatch: any);
    
  1417.   return [hook.memoizedState, dispatch];
    
  1418. }
    
  1419. 
    
  1420. function rerenderReducer<S, I, A>(
    
  1421.   reducer: (S, A) => S,
    
  1422.   initialArg: I,
    
  1423.   init?: I => S,
    
  1424. ): [S, Dispatch<A>] {
    
  1425.   const hook = updateWorkInProgressHook();
    
  1426.   const queue = hook.queue;
    
  1427. 
    
  1428.   if (queue === null) {
    
  1429.     throw new Error(
    
  1430.       'Should have a queue. This is likely a bug in React. Please file an issue.',
    
  1431.     );
    
  1432.   }
    
  1433. 
    
  1434.   queue.lastRenderedReducer = reducer;
    
  1435. 
    
  1436.   // This is a re-render. Apply the new render phase updates to the previous
    
  1437.   // work-in-progress hook.
    
  1438.   const dispatch: Dispatch<A> = (queue.dispatch: any);
    
  1439.   const lastRenderPhaseUpdate = queue.pending;
    
  1440.   let newState = hook.memoizedState;
    
  1441.   if (lastRenderPhaseUpdate !== null) {
    
  1442.     // The queue doesn't persist past this render pass.
    
  1443.     queue.pending = null;
    
  1444. 
    
  1445.     const firstRenderPhaseUpdate = lastRenderPhaseUpdate.next;
    
  1446.     let update = firstRenderPhaseUpdate;
    
  1447.     do {
    
  1448.       // Process this render phase update. We don't have to check the
    
  1449.       // priority because it will always be the same as the current
    
  1450.       // render's.
    
  1451.       const action = update.action;
    
  1452.       newState = reducer(newState, action);
    
  1453.       update = update.next;
    
  1454.     } while (update !== firstRenderPhaseUpdate);
    
  1455. 
    
  1456.     // Mark that the fiber performed work, but only if the new state is
    
  1457.     // different from the current state.
    
  1458.     if (!is(newState, hook.memoizedState)) {
    
  1459.       markWorkInProgressReceivedUpdate();
    
  1460.     }
    
  1461. 
    
  1462.     hook.memoizedState = newState;
    
  1463.     // Don't persist the state accumulated from the render phase updates to
    
  1464.     // the base state unless the queue is empty.
    
  1465.     // TODO: Not sure if this is the desired semantics, but it's what we
    
  1466.     // do for gDSFP. I can't remember why.
    
  1467.     if (hook.baseQueue === null) {
    
  1468.       hook.baseState = newState;
    
  1469.     }
    
  1470. 
    
  1471.     queue.lastRenderedState = newState;
    
  1472.   }
    
  1473.   return [newState, dispatch];
    
  1474. }
    
  1475. 
    
  1476. function mountSyncExternalStore<T>(
    
  1477.   subscribe: (() => void) => () => void,
    
  1478.   getSnapshot: () => T,
    
  1479.   getServerSnapshot?: () => T,
    
  1480. ): T {
    
  1481.   const fiber = currentlyRenderingFiber;
    
  1482.   const hook = mountWorkInProgressHook();
    
  1483. 
    
  1484.   let nextSnapshot;
    
  1485.   const isHydrating = getIsHydrating();
    
  1486.   if (isHydrating) {
    
  1487.     if (getServerSnapshot === undefined) {
    
  1488.       throw new Error(
    
  1489.         'Missing getServerSnapshot, which is required for ' +
    
  1490.           'server-rendered content. Will revert to client rendering.',
    
  1491.       );
    
  1492.     }
    
  1493.     nextSnapshot = getServerSnapshot();
    
  1494.     if (__DEV__) {
    
  1495.       if (!didWarnUncachedGetSnapshot) {
    
  1496.         if (nextSnapshot !== getServerSnapshot()) {
    
  1497.           console.error(
    
  1498.             'The result of getServerSnapshot should be cached to avoid an infinite loop',
    
  1499.           );
    
  1500.           didWarnUncachedGetSnapshot = true;
    
  1501.         }
    
  1502.       }
    
  1503.     }
    
  1504.   } else {
    
  1505.     nextSnapshot = getSnapshot();
    
  1506.     if (__DEV__) {
    
  1507.       if (!didWarnUncachedGetSnapshot) {
    
  1508.         const cachedSnapshot = getSnapshot();
    
  1509.         if (!is(nextSnapshot, cachedSnapshot)) {
    
  1510.           console.error(
    
  1511.             'The result of getSnapshot should be cached to avoid an infinite loop',
    
  1512.           );
    
  1513.           didWarnUncachedGetSnapshot = true;
    
  1514.         }
    
  1515.       }
    
  1516.     }
    
  1517.     // Unless we're rendering a blocking lane, schedule a consistency check.
    
  1518.     // Right before committing, we will walk the tree and check if any of the
    
  1519.     // stores were mutated.
    
  1520.     //
    
  1521.     // We won't do this if we're hydrating server-rendered content, because if
    
  1522.     // the content is stale, it's already visible anyway. Instead we'll patch
    
  1523.     // it up in a passive effect.
    
  1524.     const root: FiberRoot | null = getWorkInProgressRoot();
    
  1525. 
    
  1526.     if (root === null) {
    
  1527.       throw new Error(
    
  1528.         'Expected a work-in-progress root. This is a bug in React. Please file an issue.',
    
  1529.       );
    
  1530.     }
    
  1531. 
    
  1532.     const rootRenderLanes = getWorkInProgressRootRenderLanes();
    
  1533.     if (!includesBlockingLane(root, rootRenderLanes)) {
    
  1534.       pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
    
  1535.     }
    
  1536.   }
    
  1537. 
    
  1538.   // Read the current snapshot from the store on every render. This breaks the
    
  1539.   // normal rules of React, and only works because store updates are
    
  1540.   // always synchronous.
    
  1541.   hook.memoizedState = nextSnapshot;
    
  1542.   const inst: StoreInstance<T> = {
    
  1543.     value: nextSnapshot,
    
  1544.     getSnapshot,
    
  1545.   };
    
  1546.   hook.queue = inst;
    
  1547. 
    
  1548.   // Schedule an effect to subscribe to the store.
    
  1549.   mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]);
    
  1550. 
    
  1551.   // Schedule an effect to update the mutable instance fields. We will update
    
  1552.   // this whenever subscribe, getSnapshot, or value changes. Because there's no
    
  1553.   // clean-up function, and we track the deps correctly, we can call pushEffect
    
  1554.   // directly, without storing any additional state. For the same reason, we
    
  1555.   // don't need to set a static flag, either.
    
  1556.   fiber.flags |= PassiveEffect;
    
  1557.   pushEffect(
    
  1558.     HookHasEffect | HookPassive,
    
  1559.     updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),
    
  1560.     createEffectInstance(),
    
  1561.     null,
    
  1562.   );
    
  1563. 
    
  1564.   return nextSnapshot;
    
  1565. }
    
  1566. 
    
  1567. function updateSyncExternalStore<T>(
    
  1568.   subscribe: (() => void) => () => void,
    
  1569.   getSnapshot: () => T,
    
  1570.   getServerSnapshot?: () => T,
    
  1571. ): T {
    
  1572.   const fiber = currentlyRenderingFiber;
    
  1573.   const hook = updateWorkInProgressHook();
    
  1574.   // Read the current snapshot from the store on every render. This breaks the
    
  1575.   // normal rules of React, and only works because store updates are
    
  1576.   // always synchronous.
    
  1577.   let nextSnapshot;
    
  1578.   const isHydrating = getIsHydrating();
    
  1579.   if (isHydrating) {
    
  1580.     // Needed for strict mode double render
    
  1581.     if (getServerSnapshot === undefined) {
    
  1582.       throw new Error(
    
  1583.         'Missing getServerSnapshot, which is required for ' +
    
  1584.           'server-rendered content. Will revert to client rendering.',
    
  1585.       );
    
  1586.     }
    
  1587.     nextSnapshot = getServerSnapshot();
    
  1588.   } else {
    
  1589.     nextSnapshot = getSnapshot();
    
  1590.     if (__DEV__) {
    
  1591.       if (!didWarnUncachedGetSnapshot) {
    
  1592.         const cachedSnapshot = getSnapshot();
    
  1593.         if (!is(nextSnapshot, cachedSnapshot)) {
    
  1594.           console.error(
    
  1595.             'The result of getSnapshot should be cached to avoid an infinite loop',
    
  1596.           );
    
  1597.           didWarnUncachedGetSnapshot = true;
    
  1598.         }
    
  1599.       }
    
  1600.     }
    
  1601.   }
    
  1602.   const prevSnapshot = (currentHook || hook).memoizedState;
    
  1603.   const snapshotChanged = !is(prevSnapshot, nextSnapshot);
    
  1604.   if (snapshotChanged) {
    
  1605.     hook.memoizedState = nextSnapshot;
    
  1606.     markWorkInProgressReceivedUpdate();
    
  1607.   }
    
  1608.   const inst = hook.queue;
    
  1609. 
    
  1610.   updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [
    
  1611.     subscribe,
    
  1612.   ]);
    
  1613. 
    
  1614.   // Whenever getSnapshot or subscribe changes, we need to check in the
    
  1615.   // commit phase if there was an interleaved mutation. In concurrent mode
    
  1616.   // this can happen all the time, but even in synchronous mode, an earlier
    
  1617.   // effect may have mutated the store.
    
  1618.   if (
    
  1619.     inst.getSnapshot !== getSnapshot ||
    
  1620.     snapshotChanged ||
    
  1621.     // Check if the subscribe function changed. We can save some memory by
    
  1622.     // checking whether we scheduled a subscription effect above.
    
  1623.     (workInProgressHook !== null &&
    
  1624.       workInProgressHook.memoizedState.tag & HookHasEffect)
    
  1625.   ) {
    
  1626.     fiber.flags |= PassiveEffect;
    
  1627.     pushEffect(
    
  1628.       HookHasEffect | HookPassive,
    
  1629.       updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),
    
  1630.       createEffectInstance(),
    
  1631.       null,
    
  1632.     );
    
  1633. 
    
  1634.     // Unless we're rendering a blocking lane, schedule a consistency check.
    
  1635.     // Right before committing, we will walk the tree and check if any of the
    
  1636.     // stores were mutated.
    
  1637.     const root: FiberRoot | null = getWorkInProgressRoot();
    
  1638. 
    
  1639.     if (root === null) {
    
  1640.       throw new Error(
    
  1641.         'Expected a work-in-progress root. This is a bug in React. Please file an issue.',
    
  1642.       );
    
  1643.     }
    
  1644. 
    
  1645.     if (!isHydrating && !includesBlockingLane(root, renderLanes)) {
    
  1646.       pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
    
  1647.     }
    
  1648.   }
    
  1649. 
    
  1650.   return nextSnapshot;
    
  1651. }
    
  1652. 
    
  1653. function pushStoreConsistencyCheck<T>(
    
  1654.   fiber: Fiber,
    
  1655.   getSnapshot: () => T,
    
  1656.   renderedSnapshot: T,
    
  1657. ): void {
    
  1658.   fiber.flags |= StoreConsistency;
    
  1659.   const check: StoreConsistencyCheck<T> = {
    
  1660.     getSnapshot,
    
  1661.     value: renderedSnapshot,
    
  1662.   };
    
  1663.   let componentUpdateQueue: null | FunctionComponentUpdateQueue =
    
  1664.     (currentlyRenderingFiber.updateQueue: any);
    
  1665.   if (componentUpdateQueue === null) {
    
  1666.     componentUpdateQueue = createFunctionComponentUpdateQueue();
    
  1667.     currentlyRenderingFiber.updateQueue = (componentUpdateQueue: any);
    
  1668.     componentUpdateQueue.stores = [check];
    
  1669.   } else {
    
  1670.     const stores = componentUpdateQueue.stores;
    
  1671.     if (stores === null) {
    
  1672.       componentUpdateQueue.stores = [check];
    
  1673.     } else {
    
  1674.       stores.push(check);
    
  1675.     }
    
  1676.   }
    
  1677. }
    
  1678. 
    
  1679. function updateStoreInstance<T>(
    
  1680.   fiber: Fiber,
    
  1681.   inst: StoreInstance<T>,
    
  1682.   nextSnapshot: T,
    
  1683.   getSnapshot: () => T,
    
  1684. ): void {
    
  1685.   // These are updated in the passive phase
    
  1686.   inst.value = nextSnapshot;
    
  1687.   inst.getSnapshot = getSnapshot;
    
  1688. 
    
  1689.   // Something may have been mutated in between render and commit. This could
    
  1690.   // have been in an event that fired before the passive effects, or it could
    
  1691.   // have been in a layout effect. In that case, we would have used the old
    
  1692.   // snapsho and getSnapshot values to bail out. We need to check one more time.
    
  1693.   if (checkIfSnapshotChanged(inst)) {
    
  1694.     // Force a re-render.
    
  1695.     forceStoreRerender(fiber);
    
  1696.   }
    
  1697. }
    
  1698. 
    
  1699. function subscribeToStore<T>(
    
  1700.   fiber: Fiber,
    
  1701.   inst: StoreInstance<T>,
    
  1702.   subscribe: (() => void) => () => void,
    
  1703. ): any {
    
  1704.   const handleStoreChange = () => {
    
  1705.     // The store changed. Check if the snapshot changed since the last time we
    
  1706.     // read from the store.
    
  1707.     if (checkIfSnapshotChanged(inst)) {
    
  1708.       // Force a re-render.
    
  1709.       forceStoreRerender(fiber);
    
  1710.     }
    
  1711.   };
    
  1712.   // Subscribe to the store and return a clean-up function.
    
  1713.   return subscribe(handleStoreChange);
    
  1714. }
    
  1715. 
    
  1716. function checkIfSnapshotChanged<T>(inst: StoreInstance<T>): boolean {
    
  1717.   const latestGetSnapshot = inst.getSnapshot;
    
  1718.   const prevValue = inst.value;
    
  1719.   try {
    
  1720.     const nextValue = latestGetSnapshot();
    
  1721.     return !is(prevValue, nextValue);
    
  1722.   } catch (error) {
    
  1723.     return true;
    
  1724.   }
    
  1725. }
    
  1726. 
    
  1727. function forceStoreRerender(fiber: Fiber) {
    
  1728.   const root = enqueueConcurrentRenderForLane(fiber, SyncLane);
    
  1729.   if (root !== null) {
    
  1730.     scheduleUpdateOnFiber(root, fiber, SyncLane);
    
  1731.   }
    
  1732. }
    
  1733. 
    
  1734. function mountStateImpl<S>(initialState: (() => S) | S): Hook {
    
  1735.   const hook = mountWorkInProgressHook();
    
  1736.   if (typeof initialState === 'function') {
    
  1737.     // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types
    
  1738.     initialState = initialState();
    
  1739.   }
    
  1740.   hook.memoizedState = hook.baseState = initialState;
    
  1741.   const queue: UpdateQueue<S, BasicStateAction<S>> = {
    
  1742.     pending: null,
    
  1743.     lanes: NoLanes,
    
  1744.     dispatch: null,
    
  1745.     lastRenderedReducer: basicStateReducer,
    
  1746.     lastRenderedState: (initialState: any),
    
  1747.   };
    
  1748.   hook.queue = queue;
    
  1749.   return hook;
    
  1750. }
    
  1751. 
    
  1752. function mountState<S>(
    
  1753.   initialState: (() => S) | S,
    
  1754. ): [S, Dispatch<BasicStateAction<S>>] {
    
  1755.   const hook = mountStateImpl(initialState);
    
  1756.   const queue = hook.queue;
    
  1757.   const dispatch: Dispatch<BasicStateAction<S>> = (dispatchSetState.bind(
    
  1758.     null,
    
  1759.     currentlyRenderingFiber,
    
  1760.     queue,
    
  1761.   ): any);
    
  1762.   queue.dispatch = dispatch;
    
  1763.   return [hook.memoizedState, dispatch];
    
  1764. }
    
  1765. 
    
  1766. function updateState<S>(
    
  1767.   initialState: (() => S) | S,
    
  1768. ): [S, Dispatch<BasicStateAction<S>>] {
    
  1769.   return updateReducer(basicStateReducer, initialState);
    
  1770. }
    
  1771. 
    
  1772. function rerenderState<S>(
    
  1773.   initialState: (() => S) | S,
    
  1774. ): [S, Dispatch<BasicStateAction<S>>] {
    
  1775.   return rerenderReducer(basicStateReducer, initialState);
    
  1776. }
    
  1777. 
    
  1778. function mountOptimistic<S, A>(
    
  1779.   passthrough: S,
    
  1780.   reducer: ?(S, A) => S,
    
  1781. ): [S, (A) => void] {
    
  1782.   const hook = mountWorkInProgressHook();
    
  1783.   hook.memoizedState = hook.baseState = passthrough;
    
  1784.   const queue: UpdateQueue<S, A> = {
    
  1785.     pending: null,
    
  1786.     lanes: NoLanes,
    
  1787.     dispatch: null,
    
  1788.     // Optimistic state does not use the eager update optimization.
    
  1789.     lastRenderedReducer: null,
    
  1790.     lastRenderedState: null,
    
  1791.   };
    
  1792.   hook.queue = queue;
    
  1793.   // This is different than the normal setState function.
    
  1794.   const dispatch: A => void = (dispatchOptimisticSetState.bind(
    
  1795.     null,
    
  1796.     currentlyRenderingFiber,
    
  1797.     true,
    
  1798.     queue,
    
  1799.   ): any);
    
  1800.   queue.dispatch = dispatch;
    
  1801.   return [passthrough, dispatch];
    
  1802. }
    
  1803. 
    
  1804. function updateOptimistic<S, A>(
    
  1805.   passthrough: S,
    
  1806.   reducer: ?(S, A) => S,
    
  1807. ): [S, (A) => void] {
    
  1808.   const hook = updateWorkInProgressHook();
    
  1809.   return updateOptimisticImpl(
    
  1810.     hook,
    
  1811.     ((currentHook: any): Hook),
    
  1812.     passthrough,
    
  1813.     reducer,
    
  1814.   );
    
  1815. }
    
  1816. 
    
  1817. function updateOptimisticImpl<S, A>(
    
  1818.   hook: Hook,
    
  1819.   current: Hook | null,
    
  1820.   passthrough: S,
    
  1821.   reducer: ?(S, A) => S,
    
  1822. ): [S, (A) => void] {
    
  1823.   // Optimistic updates are always rebased on top of the latest value passed in
    
  1824.   // as an argument. It's called a passthrough because if there are no pending
    
  1825.   // updates, it will be returned as-is.
    
  1826.   //
    
  1827.   // Reset the base state to the passthrough. Future updates will be applied
    
  1828.   // on top of this.
    
  1829.   hook.baseState = passthrough;
    
  1830. 
    
  1831.   // If a reducer is not provided, default to the same one used by useState.
    
  1832.   const resolvedReducer: (S, A) => S =
    
  1833.     typeof reducer === 'function' ? reducer : (basicStateReducer: any);
    
  1834. 
    
  1835.   return updateReducerImpl(hook, ((currentHook: any): Hook), resolvedReducer);
    
  1836. }
    
  1837. 
    
  1838. function rerenderOptimistic<S, A>(
    
  1839.   passthrough: S,
    
  1840.   reducer: ?(S, A) => S,
    
  1841. ): [S, (A) => void] {
    
  1842.   // Unlike useState, useOptimistic doesn't support render phase updates.
    
  1843.   // Also unlike useState, we need to replay all pending updates again in case
    
  1844.   // the passthrough value changed.
    
  1845.   //
    
  1846.   // So instead of a forked re-render implementation that knows how to handle
    
  1847.   // render phase udpates, we can use the same implementation as during a
    
  1848.   // regular mount or update.
    
  1849.   const hook = updateWorkInProgressHook();
    
  1850. 
    
  1851.   if (currentHook !== null) {
    
  1852.     // This is an update. Process the update queue.
    
  1853.     return updateOptimisticImpl(
    
  1854.       hook,
    
  1855.       ((currentHook: any): Hook),
    
  1856.       passthrough,
    
  1857.       reducer,
    
  1858.     );
    
  1859.   }
    
  1860. 
    
  1861.   // This is a mount. No updates to process.
    
  1862. 
    
  1863.   // Reset the base state to the passthrough. Future updates will be applied
    
  1864.   // on top of this.
    
  1865.   hook.baseState = passthrough;
    
  1866.   const dispatch = hook.queue.dispatch;
    
  1867.   return [passthrough, dispatch];
    
  1868. }
    
  1869. 
    
  1870. // useFormState actions run sequentially, because each action receives the
    
  1871. // previous state as an argument. We store pending actions on a queue.
    
  1872. type FormStateActionQueue<S, P> = {
    
  1873.   // This is the most recent state returned from an action. It's updated as
    
  1874.   // soon as the action finishes running.
    
  1875.   state: Awaited<S>,
    
  1876.   // A stable dispatch method, passed to the user.
    
  1877.   dispatch: Dispatch<P>,
    
  1878.   // This is the most recent action function that was rendered. It's updated
    
  1879.   // during the commit phase.
    
  1880.   action: (Awaited<S>, P) => S,
    
  1881.   // This is a circular linked list of pending action payloads. It incudes the
    
  1882.   // action that is currently running.
    
  1883.   pending: FormStateActionQueueNode<P> | null,
    
  1884. };
    
  1885. 
    
  1886. type FormStateActionQueueNode<P> = {
    
  1887.   payload: P,
    
  1888.   // This is never null because it's part of a circular linked list.
    
  1889.   next: FormStateActionQueueNode<P>,
    
  1890. };
    
  1891. 
    
  1892. function dispatchFormState<S, P>(
    
  1893.   fiber: Fiber,
    
  1894.   actionQueue: FormStateActionQueue<S, P>,
    
  1895.   setState: Dispatch<S | Awaited<S>>,
    
  1896.   payload: P,
    
  1897. ): void {
    
  1898.   if (isRenderPhaseUpdate(fiber)) {
    
  1899.     throw new Error('Cannot update form state while rendering.');
    
  1900.   }
    
  1901.   const last = actionQueue.pending;
    
  1902.   if (last === null) {
    
  1903.     // There are no pending actions; this is the first one. We can run
    
  1904.     // it immediately.
    
  1905.     const newLast: FormStateActionQueueNode<P> = {
    
  1906.       payload,
    
  1907.       next: (null: any), // circular
    
  1908.     };
    
  1909.     newLast.next = actionQueue.pending = newLast;
    
  1910. 
    
  1911.     runFormStateAction(actionQueue, (setState: any), payload);
    
  1912.   } else {
    
  1913.     // There's already an action running. Add to the queue.
    
  1914.     const first = last.next;
    
  1915.     const newLast: FormStateActionQueueNode<P> = {
    
  1916.       payload,
    
  1917.       next: first,
    
  1918.     };
    
  1919.     actionQueue.pending = last.next = newLast;
    
  1920.   }
    
  1921. }
    
  1922. 
    
  1923. function runFormStateAction<S, P>(
    
  1924.   actionQueue: FormStateActionQueue<S, P>,
    
  1925.   setState: Dispatch<S | Awaited<S>>,
    
  1926.   payload: P,
    
  1927. ) {
    
  1928.   const action = actionQueue.action;
    
  1929.   const prevState = actionQueue.state;
    
  1930. 
    
  1931.   // This is a fork of startTransition
    
  1932.   const prevTransition = ReactCurrentBatchConfig.transition;
    
  1933.   ReactCurrentBatchConfig.transition = ({}: BatchConfigTransition);
    
  1934.   const currentTransition = ReactCurrentBatchConfig.transition;
    
  1935.   if (__DEV__) {
    
  1936.     ReactCurrentBatchConfig.transition._updatedFibers = new Set();
    
  1937.   }
    
  1938.   try {
    
  1939.     const returnValue = action(prevState, payload);
    
  1940.     if (
    
  1941.       returnValue !== null &&
    
  1942.       typeof returnValue === 'object' &&
    
  1943.       // $FlowFixMe[method-unbinding]
    
  1944.       typeof returnValue.then === 'function'
    
  1945.     ) {
    
  1946.       const thenable = ((returnValue: any): Thenable<Awaited<S>>);
    
  1947. 
    
  1948.       // Attach a listener to read the return state of the action. As soon as
    
  1949.       // this resolves, we can run the next action in the sequence.
    
  1950.       thenable.then(
    
  1951.         (nextState: Awaited<S>) => {
    
  1952.           actionQueue.state = nextState;
    
  1953.           finishRunningFormStateAction(actionQueue, (setState: any));
    
  1954.         },
    
  1955.         () => finishRunningFormStateAction(actionQueue, (setState: any)),
    
  1956.       );
    
  1957. 
    
  1958.       const entangledResult = requestAsyncActionContext<S>(thenable, null);
    
  1959.       setState((entangledResult: any));
    
  1960.     } else {
    
  1961.       // This is either `returnValue` or a thenable that resolves to
    
  1962.       // `returnValue`, depending on whether we're inside an async action scope.
    
  1963.       const entangledResult = requestSyncActionContext<S>(returnValue, null);
    
  1964.       setState((entangledResult: any));
    
  1965. 
    
  1966.       const nextState = ((returnValue: any): Awaited<S>);
    
  1967.       actionQueue.state = nextState;
    
  1968.       finishRunningFormStateAction(actionQueue, (setState: any));
    
  1969.     }
    
  1970.   } catch (error) {
    
  1971.     // This is a trick to get the `useFormState` hook to rethrow the error.
    
  1972.     // When it unwraps the thenable with the `use` algorithm, the error
    
  1973.     // will be thrown.
    
  1974.     const rejectedThenable: S = ({
    
  1975.       then() {},
    
  1976.       status: 'rejected',
    
  1977.       reason: error,
    
  1978.       // $FlowFixMe: Not sure why this doesn't work
    
  1979.     }: RejectedThenable<Awaited<S>>);
    
  1980.     setState(rejectedThenable);
    
  1981.     finishRunningFormStateAction(actionQueue, (setState: any));
    
  1982.   } finally {
    
  1983.     ReactCurrentBatchConfig.transition = prevTransition;
    
  1984. 
    
  1985.     if (__DEV__) {
    
  1986.       if (prevTransition === null && currentTransition._updatedFibers) {
    
  1987.         const updatedFibersCount = currentTransition._updatedFibers.size;
    
  1988.         currentTransition._updatedFibers.clear();
    
  1989.         if (updatedFibersCount > 10) {
    
  1990.           console.warn(
    
  1991.             'Detected a large number of updates inside startTransition. ' +
    
  1992.               'If this is due to a subscription please re-write it to use React provided hooks. ' +
    
  1993.               'Otherwise concurrent mode guarantees are off the table.',
    
  1994.           );
    
  1995.         }
    
  1996.       }
    
  1997.     }
    
  1998.   }
    
  1999. }
    
  2000. 
    
  2001. function finishRunningFormStateAction<S, P>(
    
  2002.   actionQueue: FormStateActionQueue<S, P>,
    
  2003.   setState: Dispatch<S | Awaited<S>>,
    
  2004. ) {
    
  2005.   // The action finished running. Pop it from the queue and run the next pending
    
  2006.   // action, if there are any.
    
  2007.   const last = actionQueue.pending;
    
  2008.   if (last !== null) {
    
  2009.     const first = last.next;
    
  2010.     if (first === last) {
    
  2011.       // This was the last action in the queue.
    
  2012.       actionQueue.pending = null;
    
  2013.     } else {
    
  2014.       // Remove the first node from the circular queue.
    
  2015.       const next = first.next;
    
  2016.       last.next = next;
    
  2017. 
    
  2018.       // Run the next action.
    
  2019.       runFormStateAction(actionQueue, (setState: any), next.payload);
    
  2020.     }
    
  2021.   }
    
  2022. }
    
  2023. 
    
  2024. function formStateReducer<S>(oldState: S, newState: S): S {
    
  2025.   return newState;
    
  2026. }
    
  2027. 
    
  2028. function mountFormState<S, P>(
    
  2029.   action: (Awaited<S>, P) => S,
    
  2030.   initialStateProp: Awaited<S>,
    
  2031.   permalink?: string,
    
  2032. ): [Awaited<S>, (P) => void] {
    
  2033.   let initialState: Awaited<S> = initialStateProp;
    
  2034.   if (getIsHydrating()) {
    
  2035.     const root: FiberRoot = (getWorkInProgressRoot(): any);
    
  2036.     const ssrFormState = root.formState;
    
  2037.     // If a formState option was passed to the root, there are form state
    
  2038.     // markers that we need to hydrate. These indicate whether the form state
    
  2039.     // matches this hook instance.
    
  2040.     if (ssrFormState !== null) {
    
  2041.       const isMatching = tryToClaimNextHydratableFormMarkerInstance(
    
  2042.         currentlyRenderingFiber,
    
  2043.       );
    
  2044.       if (isMatching) {
    
  2045.         initialState = ssrFormState[0];
    
  2046.       }
    
  2047.     }
    
  2048.   }
    
  2049. 
    
  2050.   // State hook. The state is stored in a thenable which is then unwrapped by
    
  2051.   // the `use` algorithm during render.
    
  2052.   const stateHook = mountWorkInProgressHook();
    
  2053.   stateHook.memoizedState = stateHook.baseState = initialState;
    
  2054.   // TODO: Typing this "correctly" results in recursion limit errors
    
  2055.   // const stateQueue: UpdateQueue<S | Awaited<S>, S | Awaited<S>> = {
    
  2056.   const stateQueue = {
    
  2057.     pending: null,
    
  2058.     lanes: NoLanes,
    
  2059.     dispatch: (null: any),
    
  2060.     lastRenderedReducer: formStateReducer,
    
  2061.     lastRenderedState: initialState,
    
  2062.   };
    
  2063.   stateHook.queue = stateQueue;
    
  2064.   const setState: Dispatch<S | Awaited<S>> = (dispatchSetState.bind(
    
  2065.     null,
    
  2066.     currentlyRenderingFiber,
    
  2067.     ((stateQueue: any): UpdateQueue<S | Awaited<S>, S | Awaited<S>>),
    
  2068.   ): any);
    
  2069.   stateQueue.dispatch = setState;
    
  2070. 
    
  2071.   // Action queue hook. This is used to queue pending actions. The queue is
    
  2072.   // shared between all instances of the hook. Similar to a regular state queue,
    
  2073.   // but different because the actions are run sequentially, and they run in
    
  2074.   // an event instead of during render.
    
  2075.   const actionQueueHook = mountWorkInProgressHook();
    
  2076.   const actionQueue: FormStateActionQueue<S, P> = {
    
  2077.     state: initialState,
    
  2078.     dispatch: (null: any), // circular
    
  2079.     action,
    
  2080.     pending: null,
    
  2081.   };
    
  2082.   actionQueueHook.queue = actionQueue;
    
  2083.   const dispatch = (dispatchFormState: any).bind(
    
  2084.     null,
    
  2085.     currentlyRenderingFiber,
    
  2086.     actionQueue,
    
  2087.     setState,
    
  2088.   );
    
  2089.   actionQueue.dispatch = dispatch;
    
  2090. 
    
  2091.   // Stash the action function on the memoized state of the hook. We'll use this
    
  2092.   // to detect when the action function changes so we can update it in
    
  2093.   // an effect.
    
  2094.   actionQueueHook.memoizedState = action;
    
  2095. 
    
  2096.   return [initialState, dispatch];
    
  2097. }
    
  2098. 
    
  2099. function updateFormState<S, P>(
    
  2100.   action: (Awaited<S>, P) => S,
    
  2101.   initialState: Awaited<S>,
    
  2102.   permalink?: string,
    
  2103. ): [Awaited<S>, (P) => void] {
    
  2104.   const stateHook = updateWorkInProgressHook();
    
  2105.   const currentStateHook = ((currentHook: any): Hook);
    
  2106.   return updateFormStateImpl(
    
  2107.     stateHook,
    
  2108.     currentStateHook,
    
  2109.     action,
    
  2110.     initialState,
    
  2111.     permalink,
    
  2112.   );
    
  2113. }
    
  2114. 
    
  2115. function updateFormStateImpl<S, P>(
    
  2116.   stateHook: Hook,
    
  2117.   currentStateHook: Hook,
    
  2118.   action: (Awaited<S>, P) => S,
    
  2119.   initialState: Awaited<S>,
    
  2120.   permalink?: string,
    
  2121. ): [Awaited<S>, (P) => void] {
    
  2122.   const [actionResult] = updateReducerImpl<S | Thenable<S>, S | Thenable<S>>(
    
  2123.     stateHook,
    
  2124.     currentStateHook,
    
  2125.     formStateReducer,
    
  2126.   );
    
  2127. 
    
  2128.   // This will suspend until the action finishes.
    
  2129.   const state: Awaited<S> =
    
  2130.     typeof actionResult === 'object' &&
    
  2131.     actionResult !== null &&
    
  2132.     // $FlowFixMe[method-unbinding]
    
  2133.     typeof actionResult.then === 'function'
    
  2134.       ? useThenable(((actionResult: any): Thenable<Awaited<S>>))
    
  2135.       : (actionResult: any);
    
  2136. 
    
  2137.   const actionQueueHook = updateWorkInProgressHook();
    
  2138.   const actionQueue = actionQueueHook.queue;
    
  2139.   const dispatch = actionQueue.dispatch;
    
  2140. 
    
  2141.   // Check if a new action was passed. If so, update it in an effect.
    
  2142.   const prevAction = actionQueueHook.memoizedState;
    
  2143.   if (action !== prevAction) {
    
  2144.     currentlyRenderingFiber.flags |= PassiveEffect;
    
  2145.     pushEffect(
    
  2146.       HookHasEffect | HookPassive,
    
  2147.       formStateActionEffect.bind(null, actionQueue, action),
    
  2148.       createEffectInstance(),
    
  2149.       null,
    
  2150.     );
    
  2151.   }
    
  2152. 
    
  2153.   return [state, dispatch];
    
  2154. }
    
  2155. 
    
  2156. function formStateActionEffect<S, P>(
    
  2157.   actionQueue: FormStateActionQueue<S, P>,
    
  2158.   action: (Awaited<S>, P) => S,
    
  2159. ): void {
    
  2160.   actionQueue.action = action;
    
  2161. }
    
  2162. 
    
  2163. function rerenderFormState<S, P>(
    
  2164.   action: (Awaited<S>, P) => S,
    
  2165.   initialState: Awaited<S>,
    
  2166.   permalink?: string,
    
  2167. ): [Awaited<S>, (P) => void] {
    
  2168.   // Unlike useState, useFormState doesn't support render phase updates.
    
  2169.   // Also unlike useState, we need to replay all pending updates again in case
    
  2170.   // the passthrough value changed.
    
  2171.   //
    
  2172.   // So instead of a forked re-render implementation that knows how to handle
    
  2173.   // render phase udpates, we can use the same implementation as during a
    
  2174.   // regular mount or update.
    
  2175.   const stateHook = updateWorkInProgressHook();
    
  2176.   const currentStateHook = currentHook;
    
  2177. 
    
  2178.   if (currentStateHook !== null) {
    
  2179.     // This is an update. Process the update queue.
    
  2180.     return updateFormStateImpl(
    
  2181.       stateHook,
    
  2182.       currentStateHook,
    
  2183.       action,
    
  2184.       initialState,
    
  2185.       permalink,
    
  2186.     );
    
  2187.   }
    
  2188. 
    
  2189.   // This is a mount. No updates to process.
    
  2190.   const state: Awaited<S> = stateHook.memoizedState;
    
  2191. 
    
  2192.   const actionQueueHook = updateWorkInProgressHook();
    
  2193.   const actionQueue = actionQueueHook.queue;
    
  2194.   const dispatch = actionQueue.dispatch;
    
  2195. 
    
  2196.   // This may have changed during the rerender.
    
  2197.   actionQueueHook.memoizedState = action;
    
  2198. 
    
  2199.   return [state, dispatch];
    
  2200. }
    
  2201. 
    
  2202. function pushEffect(
    
  2203.   tag: HookFlags,
    
  2204.   create: () => (() => void) | void,
    
  2205.   inst: EffectInstance,
    
  2206.   deps: Array<mixed> | null,
    
  2207. ): Effect {
    
  2208.   const effect: Effect = {
    
  2209.     tag,
    
  2210.     create,
    
  2211.     inst,
    
  2212.     deps,
    
  2213.     // Circular
    
  2214.     next: (null: any),
    
  2215.   };
    
  2216.   let componentUpdateQueue: null | FunctionComponentUpdateQueue =
    
  2217.     (currentlyRenderingFiber.updateQueue: any);
    
  2218.   if (componentUpdateQueue === null) {
    
  2219.     componentUpdateQueue = createFunctionComponentUpdateQueue();
    
  2220.     currentlyRenderingFiber.updateQueue = (componentUpdateQueue: any);
    
  2221.     componentUpdateQueue.lastEffect = effect.next = effect;
    
  2222.   } else {
    
  2223.     const lastEffect = componentUpdateQueue.lastEffect;
    
  2224.     if (lastEffect === null) {
    
  2225.       componentUpdateQueue.lastEffect = effect.next = effect;
    
  2226.     } else {
    
  2227.       const firstEffect = lastEffect.next;
    
  2228.       lastEffect.next = effect;
    
  2229.       effect.next = firstEffect;
    
  2230.       componentUpdateQueue.lastEffect = effect;
    
  2231.     }
    
  2232.   }
    
  2233.   return effect;
    
  2234. }
    
  2235. 
    
  2236. function createEffectInstance(): EffectInstance {
    
  2237.   return {destroy: undefined};
    
  2238. }
    
  2239. 
    
  2240. let stackContainsErrorMessage: boolean | null = null;
    
  2241. 
    
  2242. function getCallerStackFrame(): string {
    
  2243.   // eslint-disable-next-line react-internal/prod-error-codes
    
  2244.   const stackFrames = new Error('Error message').stack.split('\n');
    
  2245. 
    
  2246.   // Some browsers (e.g. Chrome) include the error message in the stack
    
  2247.   // but others (e.g. Firefox) do not.
    
  2248.   if (stackContainsErrorMessage === null) {
    
  2249.     stackContainsErrorMessage = stackFrames[0].includes('Error message');
    
  2250.   }
    
  2251. 
    
  2252.   return stackContainsErrorMessage
    
  2253.     ? stackFrames.slice(3, 4).join('\n')
    
  2254.     : stackFrames.slice(2, 3).join('\n');
    
  2255. }
    
  2256. 
    
  2257. function mountRef<T>(initialValue: T): {current: T} {
    
  2258.   const hook = mountWorkInProgressHook();
    
  2259.   if (enableUseRefAccessWarning) {
    
  2260.     if (__DEV__) {
    
  2261.       // Support lazy initialization pattern shown in docs.
    
  2262.       // We need to store the caller stack frame so that we don't warn on subsequent renders.
    
  2263.       let hasBeenInitialized = initialValue != null;
    
  2264.       let lazyInitGetterStack = null;
    
  2265.       let didCheckForLazyInit = false;
    
  2266. 
    
  2267.       // Only warn once per component+hook.
    
  2268.       let didWarnAboutRead = false;
    
  2269.       let didWarnAboutWrite = false;
    
  2270. 
    
  2271.       let current = initialValue;
    
  2272.       const ref = {
    
  2273.         get current() {
    
  2274.           if (!hasBeenInitialized) {
    
  2275.             didCheckForLazyInit = true;
    
  2276.             lazyInitGetterStack = getCallerStackFrame();
    
  2277.           } else if (currentlyRenderingFiber !== null && !didWarnAboutRead) {
    
  2278.             if (
    
  2279.               lazyInitGetterStack === null ||
    
  2280.               lazyInitGetterStack !== getCallerStackFrame()
    
  2281.             ) {
    
  2282.               didWarnAboutRead = true;
    
  2283.               console.warn(
    
  2284.                 '%s: Unsafe read of a mutable value during render.\n\n' +
    
  2285.                   'Reading from a ref during render is only safe if:\n' +
    
  2286.                   '1. The ref value has not been updated, or\n' +
    
  2287.                   '2. The ref holds a lazily-initialized value that is only set once.\n',
    
  2288.                 getComponentNameFromFiber(currentlyRenderingFiber) || 'Unknown',
    
  2289.               );
    
  2290.             }
    
  2291.           }
    
  2292.           return current;
    
  2293.         },
    
  2294.         set current(value: any) {
    
  2295.           if (currentlyRenderingFiber !== null && !didWarnAboutWrite) {
    
  2296.             if (hasBeenInitialized || !didCheckForLazyInit) {
    
  2297.               didWarnAboutWrite = true;
    
  2298.               console.warn(
    
  2299.                 '%s: Unsafe write of a mutable value during render.\n\n' +
    
  2300.                   'Writing to a ref during render is only safe if the ref holds ' +
    
  2301.                   'a lazily-initialized value that is only set once.\n',
    
  2302.                 getComponentNameFromFiber(currentlyRenderingFiber) || 'Unknown',
    
  2303.               );
    
  2304.             }
    
  2305.           }
    
  2306. 
    
  2307.           hasBeenInitialized = true;
    
  2308.           current = value;
    
  2309.         },
    
  2310.       };
    
  2311.       Object.seal(ref);
    
  2312.       hook.memoizedState = ref;
    
  2313.       return ref;
    
  2314.     } else {
    
  2315.       const ref = {current: initialValue};
    
  2316.       hook.memoizedState = ref;
    
  2317.       return ref;
    
  2318.     }
    
  2319.   } else {
    
  2320.     const ref = {current: initialValue};
    
  2321.     hook.memoizedState = ref;
    
  2322.     return ref;
    
  2323.   }
    
  2324. }
    
  2325. 
    
  2326. function updateRef<T>(initialValue: T): {current: T} {
    
  2327.   const hook = updateWorkInProgressHook();
    
  2328.   return hook.memoizedState;
    
  2329. }
    
  2330. 
    
  2331. function mountEffectImpl(
    
  2332.   fiberFlags: Flags,
    
  2333.   hookFlags: HookFlags,
    
  2334.   create: () => (() => void) | void,
    
  2335.   deps: Array<mixed> | void | null,
    
  2336. ): void {
    
  2337.   const hook = mountWorkInProgressHook();
    
  2338.   const nextDeps = deps === undefined ? null : deps;
    
  2339.   currentlyRenderingFiber.flags |= fiberFlags;
    
  2340.   hook.memoizedState = pushEffect(
    
  2341.     HookHasEffect | hookFlags,
    
  2342.     create,
    
  2343.     createEffectInstance(),
    
  2344.     nextDeps,
    
  2345.   );
    
  2346. }
    
  2347. 
    
  2348. function updateEffectImpl(
    
  2349.   fiberFlags: Flags,
    
  2350.   hookFlags: HookFlags,
    
  2351.   create: () => (() => void) | void,
    
  2352.   deps: Array<mixed> | void | null,
    
  2353. ): void {
    
  2354.   const hook = updateWorkInProgressHook();
    
  2355.   const nextDeps = deps === undefined ? null : deps;
    
  2356.   const effect: Effect = hook.memoizedState;
    
  2357.   const inst = effect.inst;
    
  2358. 
    
  2359.   // currentHook is null on initial mount when rerendering after a render phase
    
  2360.   // state update or for strict mode.
    
  2361.   if (currentHook !== null) {
    
  2362.     if (nextDeps !== null) {
    
  2363.       const prevEffect: Effect = currentHook.memoizedState;
    
  2364.       const prevDeps = prevEffect.deps;
    
  2365.       if (areHookInputsEqual(nextDeps, prevDeps)) {
    
  2366.         hook.memoizedState = pushEffect(hookFlags, create, inst, nextDeps);
    
  2367.         return;
    
  2368.       }
    
  2369.     }
    
  2370.   }
    
  2371. 
    
  2372.   currentlyRenderingFiber.flags |= fiberFlags;
    
  2373. 
    
  2374.   hook.memoizedState = pushEffect(
    
  2375.     HookHasEffect | hookFlags,
    
  2376.     create,
    
  2377.     inst,
    
  2378.     nextDeps,
    
  2379.   );
    
  2380. }
    
  2381. 
    
  2382. function mountEffect(
    
  2383.   create: () => (() => void) | void,
    
  2384.   deps: Array<mixed> | void | null,
    
  2385. ): void {
    
  2386.   if (
    
  2387.     __DEV__ &&
    
  2388.     (currentlyRenderingFiber.mode & StrictEffectsMode) !== NoMode &&
    
  2389.     (currentlyRenderingFiber.mode & NoStrictPassiveEffectsMode) === NoMode
    
  2390.   ) {
    
  2391.     mountEffectImpl(
    
  2392.       MountPassiveDevEffect | PassiveEffect | PassiveStaticEffect,
    
  2393.       HookPassive,
    
  2394.       create,
    
  2395.       deps,
    
  2396.     );
    
  2397.   } else {
    
  2398.     mountEffectImpl(
    
  2399.       PassiveEffect | PassiveStaticEffect,
    
  2400.       HookPassive,
    
  2401.       create,
    
  2402.       deps,
    
  2403.     );
    
  2404.   }
    
  2405. }
    
  2406. 
    
  2407. function updateEffect(
    
  2408.   create: () => (() => void) | void,
    
  2409.   deps: Array<mixed> | void | null,
    
  2410. ): void {
    
  2411.   updateEffectImpl(PassiveEffect, HookPassive, create, deps);
    
  2412. }
    
  2413. 
    
  2414. function useEffectEventImpl<Args, Return, F: (...Array<Args>) => Return>(
    
  2415.   payload: EventFunctionPayload<Args, Return, F>,
    
  2416. ) {
    
  2417.   currentlyRenderingFiber.flags |= UpdateEffect;
    
  2418.   let componentUpdateQueue: null | FunctionComponentUpdateQueue =
    
  2419.     (currentlyRenderingFiber.updateQueue: any);
    
  2420.   if (componentUpdateQueue === null) {
    
  2421.     componentUpdateQueue = createFunctionComponentUpdateQueue();
    
  2422.     currentlyRenderingFiber.updateQueue = (componentUpdateQueue: any);
    
  2423.     componentUpdateQueue.events = [payload];
    
  2424.   } else {
    
  2425.     const events = componentUpdateQueue.events;
    
  2426.     if (events === null) {
    
  2427.       componentUpdateQueue.events = [payload];
    
  2428.     } else {
    
  2429.       events.push(payload);
    
  2430.     }
    
  2431.   }
    
  2432. }
    
  2433. 
    
  2434. function mountEvent<Args, Return, F: (...Array<Args>) => Return>(
    
  2435.   callback: F,
    
  2436. ): F {
    
  2437.   const hook = mountWorkInProgressHook();
    
  2438.   const ref = {impl: callback};
    
  2439.   hook.memoizedState = ref;
    
  2440.   // $FlowIgnore[incompatible-return]
    
  2441.   return function eventFn() {
    
  2442.     if (isInvalidExecutionContextForEventFunction()) {
    
  2443.       throw new Error(
    
  2444.         "A function wrapped in useEffectEvent can't be called during rendering.",
    
  2445.       );
    
  2446.     }
    
  2447.     return ref.impl.apply(undefined, arguments);
    
  2448.   };
    
  2449. }
    
  2450. 
    
  2451. function updateEvent<Args, Return, F: (...Array<Args>) => Return>(
    
  2452.   callback: F,
    
  2453. ): F {
    
  2454.   const hook = updateWorkInProgressHook();
    
  2455.   const ref = hook.memoizedState;
    
  2456.   useEffectEventImpl({ref, nextImpl: callback});
    
  2457.   // $FlowIgnore[incompatible-return]
    
  2458.   return function eventFn() {
    
  2459.     if (isInvalidExecutionContextForEventFunction()) {
    
  2460.       throw new Error(
    
  2461.         "A function wrapped in useEffectEvent can't be called during rendering.",
    
  2462.       );
    
  2463.     }
    
  2464.     return ref.impl.apply(undefined, arguments);
    
  2465.   };
    
  2466. }
    
  2467. 
    
  2468. function mountInsertionEffect(
    
  2469.   create: () => (() => void) | void,
    
  2470.   deps: Array<mixed> | void | null,
    
  2471. ): void {
    
  2472.   mountEffectImpl(UpdateEffect, HookInsertion, create, deps);
    
  2473. }
    
  2474. 
    
  2475. function updateInsertionEffect(
    
  2476.   create: () => (() => void) | void,
    
  2477.   deps: Array<mixed> | void | null,
    
  2478. ): void {
    
  2479.   return updateEffectImpl(UpdateEffect, HookInsertion, create, deps);
    
  2480. }
    
  2481. 
    
  2482. function mountLayoutEffect(
    
  2483.   create: () => (() => void) | void,
    
  2484.   deps: Array<mixed> | void | null,
    
  2485. ): void {
    
  2486.   let fiberFlags: Flags = UpdateEffect | LayoutStaticEffect;
    
  2487.   if (
    
  2488.     __DEV__ &&
    
  2489.     (currentlyRenderingFiber.mode & StrictEffectsMode) !== NoMode
    
  2490.   ) {
    
  2491.     fiberFlags |= MountLayoutDevEffect;
    
  2492.   }
    
  2493.   return mountEffectImpl(fiberFlags, HookLayout, create, deps);
    
  2494. }
    
  2495. 
    
  2496. function updateLayoutEffect(
    
  2497.   create: () => (() => void) | void,
    
  2498.   deps: Array<mixed> | void | null,
    
  2499. ): void {
    
  2500.   return updateEffectImpl(UpdateEffect, HookLayout, create, deps);
    
  2501. }
    
  2502. 
    
  2503. function imperativeHandleEffect<T>(
    
  2504.   create: () => T,
    
  2505.   ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  2506. ): void | (() => void) {
    
  2507.   if (typeof ref === 'function') {
    
  2508.     const refCallback = ref;
    
  2509.     const inst = create();
    
  2510.     refCallback(inst);
    
  2511.     return () => {
    
  2512.       refCallback(null);
    
  2513.     };
    
  2514.   } else if (ref !== null && ref !== undefined) {
    
  2515.     const refObject = ref;
    
  2516.     if (__DEV__) {
    
  2517.       if (!refObject.hasOwnProperty('current')) {
    
  2518.         console.error(
    
  2519.           'Expected useImperativeHandle() first argument to either be a ' +
    
  2520.             'ref callback or React.createRef() object. Instead received: %s.',
    
  2521.           'an object with keys {' + Object.keys(refObject).join(', ') + '}',
    
  2522.         );
    
  2523.       }
    
  2524.     }
    
  2525.     const inst = create();
    
  2526.     refObject.current = inst;
    
  2527.     return () => {
    
  2528.       refObject.current = null;
    
  2529.     };
    
  2530.   }
    
  2531. }
    
  2532. 
    
  2533. function mountImperativeHandle<T>(
    
  2534.   ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  2535.   create: () => T,
    
  2536.   deps: Array<mixed> | void | null,
    
  2537. ): void {
    
  2538.   if (__DEV__) {
    
  2539.     if (typeof create !== 'function') {
    
  2540.       console.error(
    
  2541.         'Expected useImperativeHandle() second argument to be a function ' +
    
  2542.           'that creates a handle. Instead received: %s.',
    
  2543.         create !== null ? typeof create : 'null',
    
  2544.       );
    
  2545.     }
    
  2546.   }
    
  2547. 
    
  2548.   // TODO: If deps are provided, should we skip comparing the ref itself?
    
  2549.   const effectDeps =
    
  2550.     deps !== null && deps !== undefined ? deps.concat([ref]) : null;
    
  2551. 
    
  2552.   let fiberFlags: Flags = UpdateEffect | LayoutStaticEffect;
    
  2553.   if (
    
  2554.     __DEV__ &&
    
  2555.     (currentlyRenderingFiber.mode & StrictEffectsMode) !== NoMode
    
  2556.   ) {
    
  2557.     fiberFlags |= MountLayoutDevEffect;
    
  2558.   }
    
  2559.   mountEffectImpl(
    
  2560.     fiberFlags,
    
  2561.     HookLayout,
    
  2562.     imperativeHandleEffect.bind(null, create, ref),
    
  2563.     effectDeps,
    
  2564.   );
    
  2565. }
    
  2566. 
    
  2567. function updateImperativeHandle<T>(
    
  2568.   ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  2569.   create: () => T,
    
  2570.   deps: Array<mixed> | void | null,
    
  2571. ): void {
    
  2572.   if (__DEV__) {
    
  2573.     if (typeof create !== 'function') {
    
  2574.       console.error(
    
  2575.         'Expected useImperativeHandle() second argument to be a function ' +
    
  2576.           'that creates a handle. Instead received: %s.',
    
  2577.         create !== null ? typeof create : 'null',
    
  2578.       );
    
  2579.     }
    
  2580.   }
    
  2581. 
    
  2582.   // TODO: If deps are provided, should we skip comparing the ref itself?
    
  2583.   const effectDeps =
    
  2584.     deps !== null && deps !== undefined ? deps.concat([ref]) : null;
    
  2585. 
    
  2586.   updateEffectImpl(
    
  2587.     UpdateEffect,
    
  2588.     HookLayout,
    
  2589.     imperativeHandleEffect.bind(null, create, ref),
    
  2590.     effectDeps,
    
  2591.   );
    
  2592. }
    
  2593. 
    
  2594. function mountDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {
    
  2595.   // This hook is normally a no-op.
    
  2596.   // The react-debug-hooks package injects its own implementation
    
  2597.   // so that e.g. DevTools can display custom hook values.
    
  2598. }
    
  2599. 
    
  2600. const updateDebugValue = mountDebugValue;
    
  2601. 
    
  2602. function mountCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
    
  2603.   const hook = mountWorkInProgressHook();
    
  2604.   const nextDeps = deps === undefined ? null : deps;
    
  2605.   hook.memoizedState = [callback, nextDeps];
    
  2606.   return callback;
    
  2607. }
    
  2608. 
    
  2609. function updateCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
    
  2610.   const hook = updateWorkInProgressHook();
    
  2611.   const nextDeps = deps === undefined ? null : deps;
    
  2612.   const prevState = hook.memoizedState;
    
  2613.   if (nextDeps !== null) {
    
  2614.     const prevDeps: Array<mixed> | null = prevState[1];
    
  2615.     if (areHookInputsEqual(nextDeps, prevDeps)) {
    
  2616.       return prevState[0];
    
  2617.     }
    
  2618.   }
    
  2619.   hook.memoizedState = [callback, nextDeps];
    
  2620.   return callback;
    
  2621. }
    
  2622. 
    
  2623. function mountMemo<T>(
    
  2624.   nextCreate: () => T,
    
  2625.   deps: Array<mixed> | void | null,
    
  2626. ): T {
    
  2627.   const hook = mountWorkInProgressHook();
    
  2628.   const nextDeps = deps === undefined ? null : deps;
    
  2629.   if (shouldDoubleInvokeUserFnsInHooksDEV) {
    
  2630.     nextCreate();
    
  2631.   }
    
  2632.   const nextValue = nextCreate();
    
  2633.   hook.memoizedState = [nextValue, nextDeps];
    
  2634.   return nextValue;
    
  2635. }
    
  2636. 
    
  2637. function updateMemo<T>(
    
  2638.   nextCreate: () => T,
    
  2639.   deps: Array<mixed> | void | null,
    
  2640. ): T {
    
  2641.   const hook = updateWorkInProgressHook();
    
  2642.   const nextDeps = deps === undefined ? null : deps;
    
  2643.   const prevState = hook.memoizedState;
    
  2644.   // Assume these are defined. If they're not, areHookInputsEqual will warn.
    
  2645.   if (nextDeps !== null) {
    
  2646.     const prevDeps: Array<mixed> | null = prevState[1];
    
  2647.     if (areHookInputsEqual(nextDeps, prevDeps)) {
    
  2648.       return prevState[0];
    
  2649.     }
    
  2650.   }
    
  2651.   if (shouldDoubleInvokeUserFnsInHooksDEV) {
    
  2652.     nextCreate();
    
  2653.   }
    
  2654.   const nextValue = nextCreate();
    
  2655.   hook.memoizedState = [nextValue, nextDeps];
    
  2656.   return nextValue;
    
  2657. }
    
  2658. 
    
  2659. function mountDeferredValue<T>(value: T, initialValue?: T): T {
    
  2660.   const hook = mountWorkInProgressHook();
    
  2661.   return mountDeferredValueImpl(hook, value, initialValue);
    
  2662. }
    
  2663. 
    
  2664. function updateDeferredValue<T>(value: T, initialValue?: T): T {
    
  2665.   const hook = updateWorkInProgressHook();
    
  2666.   const resolvedCurrentHook: Hook = (currentHook: any);
    
  2667.   const prevValue: T = resolvedCurrentHook.memoizedState;
    
  2668.   return updateDeferredValueImpl(hook, prevValue, value, initialValue);
    
  2669. }
    
  2670. 
    
  2671. function rerenderDeferredValue<T>(value: T, initialValue?: T): T {
    
  2672.   const hook = updateWorkInProgressHook();
    
  2673.   if (currentHook === null) {
    
  2674.     // This is a rerender during a mount.
    
  2675.     return mountDeferredValueImpl(hook, value, initialValue);
    
  2676.   } else {
    
  2677.     // This is a rerender during an update.
    
  2678.     const prevValue: T = currentHook.memoizedState;
    
  2679.     return updateDeferredValueImpl(hook, prevValue, value, initialValue);
    
  2680.   }
    
  2681. }
    
  2682. 
    
  2683. function mountDeferredValueImpl<T>(hook: Hook, value: T, initialValue?: T): T {
    
  2684.   if (
    
  2685.     enableUseDeferredValueInitialArg &&
    
  2686.     // When `initialValue` is provided, we defer the initial render even if the
    
  2687.     // current render is not synchronous.
    
  2688.     initialValue !== undefined &&
    
  2689.     // However, to avoid waterfalls, we do not defer if this render
    
  2690.     // was itself spawned by an earlier useDeferredValue. Check if DeferredLane
    
  2691.     // is part of the render lanes.
    
  2692.     !includesSomeLane(renderLanes, DeferredLane)
    
  2693.   ) {
    
  2694.     // Render with the initial value
    
  2695.     hook.memoizedState = initialValue;
    
  2696. 
    
  2697.     // Schedule a deferred render to switch to the final value.
    
  2698.     const deferredLane = requestDeferredLane();
    
  2699.     currentlyRenderingFiber.lanes = mergeLanes(
    
  2700.       currentlyRenderingFiber.lanes,
    
  2701.       deferredLane,
    
  2702.     );
    
  2703.     markSkippedUpdateLanes(deferredLane);
    
  2704. 
    
  2705.     return initialValue;
    
  2706.   } else {
    
  2707.     hook.memoizedState = value;
    
  2708.     return value;
    
  2709.   }
    
  2710. }
    
  2711. 
    
  2712. function updateDeferredValueImpl<T>(
    
  2713.   hook: Hook,
    
  2714.   prevValue: T,
    
  2715.   value: T,
    
  2716.   initialValue?: T,
    
  2717. ): T {
    
  2718.   if (is(value, prevValue)) {
    
  2719.     // The incoming value is referentially identical to the currently rendered
    
  2720.     // value, so we can bail out quickly.
    
  2721.     return value;
    
  2722.   } else {
    
  2723.     // Received a new value that's different from the current value.
    
  2724. 
    
  2725.     // Check if we're inside a hidden tree
    
  2726.     if (isCurrentTreeHidden()) {
    
  2727.       // Revealing a prerendered tree is considered the same as mounting new
    
  2728.       // one, so we reuse the "mount" path in this case.
    
  2729.       const resultValue = mountDeferredValueImpl(hook, value, initialValue);
    
  2730.       // Unlike during an actual mount, we need to mark this as an update if
    
  2731.       // the value changed.
    
  2732.       if (!is(resultValue, prevValue)) {
    
  2733.         markWorkInProgressReceivedUpdate();
    
  2734.       }
    
  2735.       return resultValue;
    
  2736.     }
    
  2737. 
    
  2738.     const shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes);
    
  2739.     if (shouldDeferValue) {
    
  2740.       // This is an urgent update. Since the value has changed, keep using the
    
  2741.       // previous value and spawn a deferred render to update it later.
    
  2742. 
    
  2743.       // Schedule a deferred render
    
  2744.       const deferredLane = requestDeferredLane();
    
  2745.       currentlyRenderingFiber.lanes = mergeLanes(
    
  2746.         currentlyRenderingFiber.lanes,
    
  2747.         deferredLane,
    
  2748.       );
    
  2749.       markSkippedUpdateLanes(deferredLane);
    
  2750. 
    
  2751.       // Reuse the previous value. We do not need to mark this as an update,
    
  2752.       // because we did not render a new value.
    
  2753.       return prevValue;
    
  2754.     } else {
    
  2755.       // This is not an urgent update, so we can use the latest value regardless
    
  2756.       // of what it is. No need to defer it.
    
  2757. 
    
  2758.       // Mark this as an update to prevent the fiber from bailing out.
    
  2759.       markWorkInProgressReceivedUpdate();
    
  2760.       hook.memoizedState = value;
    
  2761.       return value;
    
  2762.     }
    
  2763.   }
    
  2764. }
    
  2765. 
    
  2766. function startTransition<S>(
    
  2767.   fiber: Fiber,
    
  2768.   queue: UpdateQueue<S | Thenable<S>, BasicStateAction<S | Thenable<S>>>,
    
  2769.   pendingState: S,
    
  2770.   finishedState: S,
    
  2771.   callback: () => mixed,
    
  2772.   options?: StartTransitionOptions,
    
  2773. ): void {
    
  2774.   const previousPriority = getCurrentUpdatePriority();
    
  2775.   setCurrentUpdatePriority(
    
  2776.     higherEventPriority(previousPriority, ContinuousEventPriority),
    
  2777.   );
    
  2778. 
    
  2779.   const prevTransition = ReactCurrentBatchConfig.transition;
    
  2780.   const currentTransition: BatchConfigTransition = {};
    
  2781. 
    
  2782.   if (enableAsyncActions) {
    
  2783.     // We don't really need to use an optimistic update here, because we
    
  2784.     // schedule a second "revert" update below (which we use to suspend the
    
  2785.     // transition until the async action scope has finished). But we'll use an
    
  2786.     // optimistic update anyway to make it less likely the behavior accidentally
    
  2787.     // diverges; for example, both an optimistic update and this one should
    
  2788.     // share the same lane.
    
  2789.     ReactCurrentBatchConfig.transition = currentTransition;
    
  2790.     dispatchOptimisticSetState(fiber, false, queue, pendingState);
    
  2791.   } else {
    
  2792.     ReactCurrentBatchConfig.transition = null;
    
  2793.     dispatchSetState(fiber, queue, pendingState);
    
  2794.     ReactCurrentBatchConfig.transition = currentTransition;
    
  2795.   }
    
  2796. 
    
  2797.   if (enableTransitionTracing) {
    
  2798.     if (options !== undefined && options.name !== undefined) {
    
  2799.       ReactCurrentBatchConfig.transition.name = options.name;
    
  2800.       ReactCurrentBatchConfig.transition.startTime = now();
    
  2801.     }
    
  2802.   }
    
  2803. 
    
  2804.   if (__DEV__) {
    
  2805.     ReactCurrentBatchConfig.transition._updatedFibers = new Set();
    
  2806.   }
    
  2807. 
    
  2808.   try {
    
  2809.     if (enableAsyncActions) {
    
  2810.       const returnValue = callback();
    
  2811. 
    
  2812.       // Check if we're inside an async action scope. If so, we'll entangle
    
  2813.       // this new action with the existing scope.
    
  2814.       //
    
  2815.       // If we're not already inside an async action scope, and this action is
    
  2816.       // async, then we'll create a new async scope.
    
  2817.       //
    
  2818.       // In the async case, the resulting render will suspend until the async
    
  2819.       // action scope has finished.
    
  2820.       if (
    
  2821.         returnValue !== null &&
    
  2822.         typeof returnValue === 'object' &&
    
  2823.         typeof returnValue.then === 'function'
    
  2824.       ) {
    
  2825.         const thenable = ((returnValue: any): Thenable<mixed>);
    
  2826.         // This is a thenable that resolves to `finishedState` once the async
    
  2827.         // action scope has finished.
    
  2828.         const entangledResult = requestAsyncActionContext(
    
  2829.           thenable,
    
  2830.           finishedState,
    
  2831.         );
    
  2832.         dispatchSetState(fiber, queue, entangledResult);
    
  2833.       } else {
    
  2834.         // This is either `finishedState` or a thenable that resolves to
    
  2835.         // `finishedState`, depending on whether we're inside an async
    
  2836.         // action scope.
    
  2837.         const entangledResult = requestSyncActionContext(
    
  2838.           returnValue,
    
  2839.           finishedState,
    
  2840.         );
    
  2841.         dispatchSetState(fiber, queue, entangledResult);
    
  2842.       }
    
  2843.     } else {
    
  2844.       // Async actions are not enabled.
    
  2845.       dispatchSetState(fiber, queue, finishedState);
    
  2846.       callback();
    
  2847.     }
    
  2848.   } catch (error) {
    
  2849.     if (enableAsyncActions) {
    
  2850.       // This is a trick to get the `useTransition` hook to rethrow the error.
    
  2851.       // When it unwraps the thenable with the `use` algorithm, the error
    
  2852.       // will be thrown.
    
  2853.       const rejectedThenable: RejectedThenable<S> = {
    
  2854.         then() {},
    
  2855.         status: 'rejected',
    
  2856.         reason: error,
    
  2857.       };
    
  2858.       dispatchSetState(fiber, queue, rejectedThenable);
    
  2859.     } else {
    
  2860.       // The error rethrowing behavior is only enabled when the async actions
    
  2861.       // feature is on, even for sync actions.
    
  2862.       throw error;
    
  2863.     }
    
  2864.   } finally {
    
  2865.     setCurrentUpdatePriority(previousPriority);
    
  2866. 
    
  2867.     ReactCurrentBatchConfig.transition = prevTransition;
    
  2868. 
    
  2869.     if (__DEV__) {
    
  2870.       if (prevTransition === null && currentTransition._updatedFibers) {
    
  2871.         const updatedFibersCount = currentTransition._updatedFibers.size;
    
  2872.         currentTransition._updatedFibers.clear();
    
  2873.         if (updatedFibersCount > 10) {
    
  2874.           console.warn(
    
  2875.             'Detected a large number of updates inside startTransition. ' +
    
  2876.               'If this is due to a subscription please re-write it to use React provided hooks. ' +
    
  2877.               'Otherwise concurrent mode guarantees are off the table.',
    
  2878.           );
    
  2879.         }
    
  2880.       }
    
  2881.     }
    
  2882.   }
    
  2883. }
    
  2884. 
    
  2885. export function startHostTransition<F>(
    
  2886.   formFiber: Fiber,
    
  2887.   pendingState: TransitionStatus,
    
  2888.   callback: F => mixed,
    
  2889.   formData: F,
    
  2890. ): void {
    
  2891.   if (!enableFormActions) {
    
  2892.     // Not implemented.
    
  2893.     return;
    
  2894.   }
    
  2895. 
    
  2896.   if (!enableAsyncActions) {
    
  2897.     // Form actions are enabled, but async actions are not. Call the function,
    
  2898.     // but don't handle any pending or error states.
    
  2899.     callback(formData);
    
  2900.     return;
    
  2901.   }
    
  2902. 
    
  2903.   if (formFiber.tag !== HostComponent) {
    
  2904.     throw new Error(
    
  2905.       'Expected the form instance to be a HostComponent. This ' +
    
  2906.         'is a bug in React.',
    
  2907.     );
    
  2908.   }
    
  2909. 
    
  2910.   let queue: UpdateQueue<
    
  2911.     Thenable<TransitionStatus> | TransitionStatus,
    
  2912.     BasicStateAction<Thenable<TransitionStatus> | TransitionStatus>,
    
  2913.   >;
    
  2914.   if (formFiber.memoizedState === null) {
    
  2915.     // Upgrade this host component fiber to be stateful. We're going to pretend
    
  2916.     // it was stateful all along so we can reuse most of the implementation
    
  2917.     // for function components and useTransition.
    
  2918.     //
    
  2919.     // Create the state hook used by TransitionAwareHostComponent. This is
    
  2920.     // essentially an inlined version of mountState.
    
  2921.     const newQueue: UpdateQueue<
    
  2922.       Thenable<TransitionStatus> | TransitionStatus,
    
  2923.       BasicStateAction<Thenable<TransitionStatus> | TransitionStatus>,
    
  2924.     > = {
    
  2925.       pending: null,
    
  2926.       lanes: NoLanes,
    
  2927.       // We're going to cheat and intentionally not create a bound dispatch
    
  2928.       // method, because we can call it directly in startTransition.
    
  2929.       dispatch: (null: any),
    
  2930.       lastRenderedReducer: basicStateReducer,
    
  2931.       lastRenderedState: NoPendingHostTransition,
    
  2932.     };
    
  2933.     queue = newQueue;
    
  2934. 
    
  2935.     const stateHook: Hook = {
    
  2936.       memoizedState: NoPendingHostTransition,
    
  2937.       baseState: NoPendingHostTransition,
    
  2938.       baseQueue: null,
    
  2939.       queue: newQueue,
    
  2940.       next: null,
    
  2941.     };
    
  2942. 
    
  2943.     // Add the state hook to both fiber alternates. The idea is that the fiber
    
  2944.     // had this hook all along.
    
  2945.     formFiber.memoizedState = stateHook;
    
  2946.     const alternate = formFiber.alternate;
    
  2947.     if (alternate !== null) {
    
  2948.       alternate.memoizedState = stateHook;
    
  2949.     }
    
  2950.   } else {
    
  2951.     // This fiber was already upgraded to be stateful.
    
  2952.     const stateHook: Hook = formFiber.memoizedState;
    
  2953.     queue = stateHook.queue;
    
  2954.   }
    
  2955. 
    
  2956.   startTransition(
    
  2957.     formFiber,
    
  2958.     queue,
    
  2959.     pendingState,
    
  2960.     NoPendingHostTransition,
    
  2961.     // TODO: We can avoid this extra wrapper, somehow. Figure out layering
    
  2962.     // once more of this function is implemented.
    
  2963.     () => callback(formData),
    
  2964.   );
    
  2965. }
    
  2966. 
    
  2967. function mountTransition(): [
    
  2968.   boolean,
    
  2969.   (callback: () => void, options?: StartTransitionOptions) => void,
    
  2970. ] {
    
  2971.   const stateHook = mountStateImpl((false: Thenable<boolean> | boolean));
    
  2972.   // The `start` method never changes.
    
  2973.   const start = startTransition.bind(
    
  2974.     null,
    
  2975.     currentlyRenderingFiber,
    
  2976.     stateHook.queue,
    
  2977.     true,
    
  2978.     false,
    
  2979.   );
    
  2980.   const hook = mountWorkInProgressHook();
    
  2981.   hook.memoizedState = start;
    
  2982.   return [false, start];
    
  2983. }
    
  2984. 
    
  2985. function updateTransition(): [
    
  2986.   boolean,
    
  2987.   (callback: () => void, options?: StartTransitionOptions) => void,
    
  2988. ] {
    
  2989.   const [booleanOrThenable] = updateState(false);
    
  2990.   const hook = updateWorkInProgressHook();
    
  2991.   const start = hook.memoizedState;
    
  2992.   const isPending =
    
  2993.     typeof booleanOrThenable === 'boolean'
    
  2994.       ? booleanOrThenable
    
  2995.       : // This will suspend until the async action scope has finished.
    
  2996.         useThenable(booleanOrThenable);
    
  2997.   return [isPending, start];
    
  2998. }
    
  2999. 
    
  3000. function rerenderTransition(): [
    
  3001.   boolean,
    
  3002.   (callback: () => void, options?: StartTransitionOptions) => void,
    
  3003. ] {
    
  3004.   const [booleanOrThenable] = rerenderState(false);
    
  3005.   const hook = updateWorkInProgressHook();
    
  3006.   const start = hook.memoizedState;
    
  3007.   const isPending =
    
  3008.     typeof booleanOrThenable === 'boolean'
    
  3009.       ? booleanOrThenable
    
  3010.       : // This will suspend until the async action scope has finished.
    
  3011.         useThenable(booleanOrThenable);
    
  3012.   return [isPending, start];
    
  3013. }
    
  3014. 
    
  3015. function useHostTransitionStatus(): TransitionStatus {
    
  3016.   if (!(enableFormActions && enableAsyncActions)) {
    
  3017.     throw new Error('Not implemented.');
    
  3018.   }
    
  3019.   const status: TransitionStatus | null = readContext(HostTransitionContext);
    
  3020.   return status !== null ? status : NoPendingHostTransition;
    
  3021. }
    
  3022. 
    
  3023. function mountId(): string {
    
  3024.   const hook = mountWorkInProgressHook();
    
  3025. 
    
  3026.   const root = ((getWorkInProgressRoot(): any): FiberRoot);
    
  3027.   // TODO: In Fizz, id generation is specific to each server config. Maybe we
    
  3028.   // should do this in Fiber, too? Deferring this decision for now because
    
  3029.   // there's no other place to store the prefix except for an internal field on
    
  3030.   // the public createRoot object, which the fiber tree does not currently have
    
  3031.   // a reference to.
    
  3032.   const identifierPrefix = root.identifierPrefix;
    
  3033. 
    
  3034.   let id;
    
  3035.   if (getIsHydrating()) {
    
  3036.     const treeId = getTreeId();
    
  3037. 
    
  3038.     // Use a captial R prefix for server-generated ids.
    
  3039.     id = ':' + identifierPrefix + 'R' + treeId;
    
  3040. 
    
  3041.     // Unless this is the first id at this level, append a number at the end
    
  3042.     // that represents the position of this useId hook among all the useId
    
  3043.     // hooks for this fiber.
    
  3044.     const localId = localIdCounter++;
    
  3045.     if (localId > 0) {
    
  3046.       id += 'H' + localId.toString(32);
    
  3047.     }
    
  3048. 
    
  3049.     id += ':';
    
  3050.   } else {
    
  3051.     // Use a lowercase r prefix for client-generated ids.
    
  3052.     const globalClientId = globalClientIdCounter++;
    
  3053.     id = ':' + identifierPrefix + 'r' + globalClientId.toString(32) + ':';
    
  3054.   }
    
  3055. 
    
  3056.   hook.memoizedState = id;
    
  3057.   return id;
    
  3058. }
    
  3059. 
    
  3060. function updateId(): string {
    
  3061.   const hook = updateWorkInProgressHook();
    
  3062.   const id: string = hook.memoizedState;
    
  3063.   return id;
    
  3064. }
    
  3065. 
    
  3066. function mountRefresh(): any {
    
  3067.   const hook = mountWorkInProgressHook();
    
  3068.   const refresh = (hook.memoizedState = refreshCache.bind(
    
  3069.     null,
    
  3070.     currentlyRenderingFiber,
    
  3071.   ));
    
  3072.   return refresh;
    
  3073. }
    
  3074. 
    
  3075. function updateRefresh(): any {
    
  3076.   const hook = updateWorkInProgressHook();
    
  3077.   return hook.memoizedState;
    
  3078. }
    
  3079. 
    
  3080. function refreshCache<T>(fiber: Fiber, seedKey: ?() => T, seedValue: T): void {
    
  3081.   if (!enableCache) {
    
  3082.     return;
    
  3083.   }
    
  3084.   // TODO: Does Cache work in legacy mode? Should decide and write a test.
    
  3085.   // TODO: Consider warning if the refresh is at discrete priority, or if we
    
  3086.   // otherwise suspect that it wasn't batched properly.
    
  3087.   let provider = fiber.return;
    
  3088.   while (provider !== null) {
    
  3089.     switch (provider.tag) {
    
  3090.       case CacheComponent:
    
  3091.       case HostRoot: {
    
  3092.         // Schedule an update on the cache boundary to trigger a refresh.
    
  3093.         const lane = requestUpdateLane(provider);
    
  3094.         const refreshUpdate = createLegacyQueueUpdate(lane);
    
  3095.         const root = enqueueLegacyQueueUpdate(provider, refreshUpdate, lane);
    
  3096.         if (root !== null) {
    
  3097.           scheduleUpdateOnFiber(root, provider, lane);
    
  3098.           entangleLegacyQueueTransitions(root, provider, lane);
    
  3099.         }
    
  3100. 
    
  3101.         // TODO: If a refresh never commits, the new cache created here must be
    
  3102.         // released. A simple case is start refreshing a cache boundary, but then
    
  3103.         // unmount that boundary before the refresh completes.
    
  3104.         const seededCache = createCache();
    
  3105.         if (seedKey !== null && seedKey !== undefined && root !== null) {
    
  3106.           if (enableLegacyCache) {
    
  3107.             // Seed the cache with the value passed by the caller. This could be
    
  3108.             // from a server mutation, or it could be a streaming response.
    
  3109.             seededCache.data.set(seedKey, seedValue);
    
  3110.           } else {
    
  3111.             if (__DEV__) {
    
  3112.               console.error(
    
  3113.                 'The seed argument is not enabled outside experimental channels.',
    
  3114.               );
    
  3115.             }
    
  3116.           }
    
  3117.         }
    
  3118. 
    
  3119.         const payload = {
    
  3120.           cache: seededCache,
    
  3121.         };
    
  3122.         refreshUpdate.payload = payload;
    
  3123.         return;
    
  3124.       }
    
  3125.     }
    
  3126.     provider = provider.return;
    
  3127.   }
    
  3128.   // TODO: Warn if unmounted?
    
  3129. }
    
  3130. 
    
  3131. function dispatchReducerAction<S, A>(
    
  3132.   fiber: Fiber,
    
  3133.   queue: UpdateQueue<S, A>,
    
  3134.   action: A,
    
  3135. ): void {
    
  3136.   if (__DEV__) {
    
  3137.     if (typeof arguments[3] === 'function') {
    
  3138.       console.error(
    
  3139.         "State updates from the useState() and useReducer() Hooks don't support the " +
    
  3140.           'second callback argument. To execute a side effect after ' +
    
  3141.           'rendering, declare it in the component body with useEffect().',
    
  3142.       );
    
  3143.     }
    
  3144.   }
    
  3145. 
    
  3146.   const lane = requestUpdateLane(fiber);
    
  3147. 
    
  3148.   const update: Update<S, A> = {
    
  3149.     lane,
    
  3150.     revertLane: NoLane,
    
  3151.     action,
    
  3152.     hasEagerState: false,
    
  3153.     eagerState: null,
    
  3154.     next: (null: any),
    
  3155.   };
    
  3156. 
    
  3157.   if (isRenderPhaseUpdate(fiber)) {
    
  3158.     enqueueRenderPhaseUpdate(queue, update);
    
  3159.   } else {
    
  3160.     const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
    
  3161.     if (root !== null) {
    
  3162.       scheduleUpdateOnFiber(root, fiber, lane);
    
  3163.       entangleTransitionUpdate(root, queue, lane);
    
  3164.     }
    
  3165.   }
    
  3166. 
    
  3167.   markUpdateInDevTools(fiber, lane, action);
    
  3168. }
    
  3169. 
    
  3170. function dispatchSetState<S, A>(
    
  3171.   fiber: Fiber,
    
  3172.   queue: UpdateQueue<S, A>,
    
  3173.   action: A,
    
  3174. ): void {
    
  3175.   if (__DEV__) {
    
  3176.     if (typeof arguments[3] === 'function') {
    
  3177.       console.error(
    
  3178.         "State updates from the useState() and useReducer() Hooks don't support the " +
    
  3179.           'second callback argument. To execute a side effect after ' +
    
  3180.           'rendering, declare it in the component body with useEffect().',
    
  3181.       );
    
  3182.     }
    
  3183.   }
    
  3184. 
    
  3185.   const lane = requestUpdateLane(fiber);
    
  3186. 
    
  3187.   const update: Update<S, A> = {
    
  3188.     lane,
    
  3189.     revertLane: NoLane,
    
  3190.     action,
    
  3191.     hasEagerState: false,
    
  3192.     eagerState: null,
    
  3193.     next: (null: any),
    
  3194.   };
    
  3195. 
    
  3196.   if (isRenderPhaseUpdate(fiber)) {
    
  3197.     enqueueRenderPhaseUpdate(queue, update);
    
  3198.   } else {
    
  3199.     const alternate = fiber.alternate;
    
  3200.     if (
    
  3201.       fiber.lanes === NoLanes &&
    
  3202.       (alternate === null || alternate.lanes === NoLanes)
    
  3203.     ) {
    
  3204.       // The queue is currently empty, which means we can eagerly compute the
    
  3205.       // next state before entering the render phase. If the new state is the
    
  3206.       // same as the current state, we may be able to bail out entirely.
    
  3207.       const lastRenderedReducer = queue.lastRenderedReducer;
    
  3208.       if (lastRenderedReducer !== null) {
    
  3209.         let prevDispatcher;
    
  3210.         if (__DEV__) {
    
  3211.           prevDispatcher = ReactCurrentDispatcher.current;
    
  3212.           ReactCurrentDispatcher.current =
    
  3213.             InvalidNestedHooksDispatcherOnUpdateInDEV;
    
  3214.         }
    
  3215.         try {
    
  3216.           const currentState: S = (queue.lastRenderedState: any);
    
  3217.           const eagerState = lastRenderedReducer(currentState, action);
    
  3218.           // Stash the eagerly computed state, and the reducer used to compute
    
  3219.           // it, on the update object. If the reducer hasn't changed by the
    
  3220.           // time we enter the render phase, then the eager state can be used
    
  3221.           // without calling the reducer again.
    
  3222.           update.hasEagerState = true;
    
  3223.           update.eagerState = eagerState;
    
  3224.           if (is(eagerState, currentState)) {
    
  3225.             // Fast path. We can bail out without scheduling React to re-render.
    
  3226.             // It's still possible that we'll need to rebase this update later,
    
  3227.             // if the component re-renders for a different reason and by that
    
  3228.             // time the reducer has changed.
    
  3229.             // TODO: Do we still need to entangle transitions in this case?
    
  3230.             enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update);
    
  3231.             return;
    
  3232.           }
    
  3233.         } catch (error) {
    
  3234.           // Suppress the error. It will throw again in the render phase.
    
  3235.         } finally {
    
  3236.           if (__DEV__) {
    
  3237.             ReactCurrentDispatcher.current = prevDispatcher;
    
  3238.           }
    
  3239.         }
    
  3240.       }
    
  3241.     }
    
  3242. 
    
  3243.     const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
    
  3244.     if (root !== null) {
    
  3245.       scheduleUpdateOnFiber(root, fiber, lane);
    
  3246.       entangleTransitionUpdate(root, queue, lane);
    
  3247.     }
    
  3248.   }
    
  3249. 
    
  3250.   markUpdateInDevTools(fiber, lane, action);
    
  3251. }
    
  3252. 
    
  3253. function dispatchOptimisticSetState<S, A>(
    
  3254.   fiber: Fiber,
    
  3255.   throwIfDuringRender: boolean,
    
  3256.   queue: UpdateQueue<S, A>,
    
  3257.   action: A,
    
  3258. ): void {
    
  3259.   if (__DEV__) {
    
  3260.     if (ReactCurrentBatchConfig.transition === null) {
    
  3261.       // An optimistic update occurred, but startTransition is not on the stack.
    
  3262.       // There are two likely scenarios.
    
  3263. 
    
  3264.       // One possibility is that the optimistic update is triggered by a regular
    
  3265.       // event handler (e.g. `onSubmit`) instead of an action. This is a mistake
    
  3266.       // and we will warn.
    
  3267. 
    
  3268.       // The other possibility is the optimistic update is inside an async
    
  3269.       // action, but after an `await`. In this case, we can make it "just work"
    
  3270.       // by associating the optimistic update with the pending async action.
    
  3271. 
    
  3272.       // Technically it's possible that the optimistic update is unrelated to
    
  3273.       // the pending action, but we don't have a way of knowing this for sure
    
  3274.       // because browsers currently do not provide a way to track async scope.
    
  3275.       // (The AsyncContext proposal, if it lands, will solve this in the
    
  3276.       // future.) However, this is no different than the problem of unrelated
    
  3277.       // transitions being grouped together — it's not wrong per se, but it's
    
  3278.       // not ideal.
    
  3279. 
    
  3280.       // Once AsyncContext starts landing in browsers, we will provide better
    
  3281.       // warnings in development for these cases.
    
  3282.       if (peekEntangledActionLane() !== NoLane) {
    
  3283.         // There is a pending async action. Don't warn.
    
  3284.       } else {
    
  3285.         // There's no pending async action. The most likely cause is that we're
    
  3286.         // inside a regular event handler (e.g. onSubmit) instead of an action.
    
  3287.         console.error(
    
  3288.           'An optimistic state update occurred outside a transition or ' +
    
  3289.             'action. To fix, move the update to an action, or wrap ' +
    
  3290.             'with startTransition.',
    
  3291.         );
    
  3292.       }
    
  3293.     }
    
  3294.   }
    
  3295. 
    
  3296.   const update: Update<S, A> = {
    
  3297.     // An optimistic update commits synchronously.
    
  3298.     lane: SyncLane,
    
  3299.     // After committing, the optimistic update is "reverted" using the same
    
  3300.     // lane as the transition it's associated with.
    
  3301.     revertLane: requestTransitionLane(),
    
  3302.     action,
    
  3303.     hasEagerState: false,
    
  3304.     eagerState: null,
    
  3305.     next: (null: any),
    
  3306.   };
    
  3307. 
    
  3308.   if (isRenderPhaseUpdate(fiber)) {
    
  3309.     // When calling startTransition during render, this warns instead of
    
  3310.     // throwing because throwing would be a breaking change. setOptimisticState
    
  3311.     // is a new API so it's OK to throw.
    
  3312.     if (throwIfDuringRender) {
    
  3313.       throw new Error('Cannot update optimistic state while rendering.');
    
  3314.     } else {
    
  3315.       // startTransition was called during render. We don't need to do anything
    
  3316.       // besides warn here because the render phase update would be overidden by
    
  3317.       // the second update, anyway. We can remove this branch and make it throw
    
  3318.       // in a future release.
    
  3319.       if (__DEV__) {
    
  3320.         console.error('Cannot call startTransition while rendering.');
    
  3321.       }
    
  3322.     }
    
  3323.   } else {
    
  3324.     const root = enqueueConcurrentHookUpdate(fiber, queue, update, SyncLane);
    
  3325.     if (root !== null) {
    
  3326.       // NOTE: The optimistic update implementation assumes that the transition
    
  3327.       // will never be attempted before the optimistic update. This currently
    
  3328.       // holds because the optimistic update is always synchronous. If we ever
    
  3329.       // change that, we'll need to account for this.
    
  3330.       scheduleUpdateOnFiber(root, fiber, SyncLane);
    
  3331.       // Optimistic updates are always synchronous, so we don't need to call
    
  3332.       // entangleTransitionUpdate here.
    
  3333.     }
    
  3334.   }
    
  3335. 
    
  3336.   markUpdateInDevTools(fiber, SyncLane, action);
    
  3337. }
    
  3338. 
    
  3339. function isRenderPhaseUpdate(fiber: Fiber): boolean {
    
  3340.   const alternate = fiber.alternate;
    
  3341.   return (
    
  3342.     fiber === currentlyRenderingFiber ||
    
  3343.     (alternate !== null && alternate === currentlyRenderingFiber)
    
  3344.   );
    
  3345. }
    
  3346. 
    
  3347. function enqueueRenderPhaseUpdate<S, A>(
    
  3348.   queue: UpdateQueue<S, A>,
    
  3349.   update: Update<S, A>,
    
  3350. ): void {
    
  3351.   // This is a render phase update. Stash it in a lazily-created map of
    
  3352.   // queue -> linked list of updates. After this render pass, we'll restart
    
  3353.   // and apply the stashed updates on top of the work-in-progress hook.
    
  3354.   didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate =
    
  3355.     true;
    
  3356.   const pending = queue.pending;
    
  3357.   if (pending === null) {
    
  3358.     // This is the first update. Create a circular list.
    
  3359.     update.next = update;
    
  3360.   } else {
    
  3361.     update.next = pending.next;
    
  3362.     pending.next = update;
    
  3363.   }
    
  3364.   queue.pending = update;
    
  3365. }
    
  3366. 
    
  3367. // TODO: Move to ReactFiberConcurrentUpdates?
    
  3368. function entangleTransitionUpdate<S, A>(
    
  3369.   root: FiberRoot,
    
  3370.   queue: UpdateQueue<S, A>,
    
  3371.   lane: Lane,
    
  3372. ): void {
    
  3373.   if (isTransitionLane(lane)) {
    
  3374.     let queueLanes = queue.lanes;
    
  3375. 
    
  3376.     // If any entangled lanes are no longer pending on the root, then they
    
  3377.     // must have finished. We can remove them from the shared queue, which
    
  3378.     // represents a superset of the actually pending lanes. In some cases we
    
  3379.     // may entangle more than we need to, but that's OK. In fact it's worse if
    
  3380.     // we *don't* entangle when we should.
    
  3381.     queueLanes = intersectLanes(queueLanes, root.pendingLanes);
    
  3382. 
    
  3383.     // Entangle the new transition lane with the other transition lanes.
    
  3384.     const newQueueLanes = mergeLanes(queueLanes, lane);
    
  3385.     queue.lanes = newQueueLanes;
    
  3386.     // Even if queue.lanes already include lane, we don't know for certain if
    
  3387.     // the lane finished since the last time we entangled it. So we need to
    
  3388.     // entangle it again, just to be sure.
    
  3389.     markRootEntangled(root, newQueueLanes);
    
  3390.   }
    
  3391. }
    
  3392. 
    
  3393. function markUpdateInDevTools<A>(fiber: Fiber, lane: Lane, action: A): void {
    
  3394.   if (__DEV__) {
    
  3395.     if (enableDebugTracing) {
    
  3396.       if (fiber.mode & DebugTracingMode) {
    
  3397.         const name = getComponentNameFromFiber(fiber) || 'Unknown';
    
  3398.         logStateUpdateScheduled(name, lane, action);
    
  3399.       }
    
  3400.     }
    
  3401.   }
    
  3402. 
    
  3403.   if (enableSchedulingProfiler) {
    
  3404.     markStateUpdateScheduled(fiber, lane);
    
  3405.   }
    
  3406. }
    
  3407. 
    
  3408. export const ContextOnlyDispatcher: Dispatcher = {
    
  3409.   readContext,
    
  3410. 
    
  3411.   use,
    
  3412.   useCallback: throwInvalidHookError,
    
  3413.   useContext: throwInvalidHookError,
    
  3414.   useEffect: throwInvalidHookError,
    
  3415.   useImperativeHandle: throwInvalidHookError,
    
  3416.   useInsertionEffect: throwInvalidHookError,
    
  3417.   useLayoutEffect: throwInvalidHookError,
    
  3418.   useMemo: throwInvalidHookError,
    
  3419.   useReducer: throwInvalidHookError,
    
  3420.   useRef: throwInvalidHookError,
    
  3421.   useState: throwInvalidHookError,
    
  3422.   useDebugValue: throwInvalidHookError,
    
  3423.   useDeferredValue: throwInvalidHookError,
    
  3424.   useTransition: throwInvalidHookError,
    
  3425.   useSyncExternalStore: throwInvalidHookError,
    
  3426.   useId: throwInvalidHookError,
    
  3427. };
    
  3428. if (enableCache) {
    
  3429.   (ContextOnlyDispatcher: Dispatcher).useCacheRefresh = throwInvalidHookError;
    
  3430. }
    
  3431. if (enableUseMemoCacheHook) {
    
  3432.   (ContextOnlyDispatcher: Dispatcher).useMemoCache = throwInvalidHookError;
    
  3433. }
    
  3434. if (enableUseEffectEventHook) {
    
  3435.   (ContextOnlyDispatcher: Dispatcher).useEffectEvent = throwInvalidHookError;
    
  3436. }
    
  3437. if (enableFormActions && enableAsyncActions) {
    
  3438.   (ContextOnlyDispatcher: Dispatcher).useHostTransitionStatus =
    
  3439.     throwInvalidHookError;
    
  3440.   (ContextOnlyDispatcher: Dispatcher).useFormState = throwInvalidHookError;
    
  3441. }
    
  3442. if (enableAsyncActions) {
    
  3443.   (ContextOnlyDispatcher: Dispatcher).useOptimistic = throwInvalidHookError;
    
  3444. }
    
  3445. 
    
  3446. const HooksDispatcherOnMount: Dispatcher = {
    
  3447.   readContext,
    
  3448. 
    
  3449.   use,
    
  3450.   useCallback: mountCallback,
    
  3451.   useContext: readContext,
    
  3452.   useEffect: mountEffect,
    
  3453.   useImperativeHandle: mountImperativeHandle,
    
  3454.   useLayoutEffect: mountLayoutEffect,
    
  3455.   useInsertionEffect: mountInsertionEffect,
    
  3456.   useMemo: mountMemo,
    
  3457.   useReducer: mountReducer,
    
  3458.   useRef: mountRef,
    
  3459.   useState: mountState,
    
  3460.   useDebugValue: mountDebugValue,
    
  3461.   useDeferredValue: mountDeferredValue,
    
  3462.   useTransition: mountTransition,
    
  3463.   useSyncExternalStore: mountSyncExternalStore,
    
  3464.   useId: mountId,
    
  3465. };
    
  3466. if (enableCache) {
    
  3467.   (HooksDispatcherOnMount: Dispatcher).useCacheRefresh = mountRefresh;
    
  3468. }
    
  3469. if (enableUseMemoCacheHook) {
    
  3470.   (HooksDispatcherOnMount: Dispatcher).useMemoCache = useMemoCache;
    
  3471. }
    
  3472. if (enableUseEffectEventHook) {
    
  3473.   (HooksDispatcherOnMount: Dispatcher).useEffectEvent = mountEvent;
    
  3474. }
    
  3475. if (enableFormActions && enableAsyncActions) {
    
  3476.   (HooksDispatcherOnMount: Dispatcher).useHostTransitionStatus =
    
  3477.     useHostTransitionStatus;
    
  3478.   (HooksDispatcherOnMount: Dispatcher).useFormState = mountFormState;
    
  3479. }
    
  3480. if (enableAsyncActions) {
    
  3481.   (HooksDispatcherOnMount: Dispatcher).useOptimistic = mountOptimistic;
    
  3482. }
    
  3483. 
    
  3484. const HooksDispatcherOnUpdate: Dispatcher = {
    
  3485.   readContext,
    
  3486. 
    
  3487.   use,
    
  3488.   useCallback: updateCallback,
    
  3489.   useContext: readContext,
    
  3490.   useEffect: updateEffect,
    
  3491.   useImperativeHandle: updateImperativeHandle,
    
  3492.   useInsertionEffect: updateInsertionEffect,
    
  3493.   useLayoutEffect: updateLayoutEffect,
    
  3494.   useMemo: updateMemo,
    
  3495.   useReducer: updateReducer,
    
  3496.   useRef: updateRef,
    
  3497.   useState: updateState,
    
  3498.   useDebugValue: updateDebugValue,
    
  3499.   useDeferredValue: updateDeferredValue,
    
  3500.   useTransition: updateTransition,
    
  3501.   useSyncExternalStore: updateSyncExternalStore,
    
  3502.   useId: updateId,
    
  3503. };
    
  3504. if (enableCache) {
    
  3505.   (HooksDispatcherOnUpdate: Dispatcher).useCacheRefresh = updateRefresh;
    
  3506. }
    
  3507. if (enableUseMemoCacheHook) {
    
  3508.   (HooksDispatcherOnUpdate: Dispatcher).useMemoCache = useMemoCache;
    
  3509. }
    
  3510. if (enableUseEffectEventHook) {
    
  3511.   (HooksDispatcherOnUpdate: Dispatcher).useEffectEvent = updateEvent;
    
  3512. }
    
  3513. if (enableFormActions && enableAsyncActions) {
    
  3514.   (HooksDispatcherOnUpdate: Dispatcher).useHostTransitionStatus =
    
  3515.     useHostTransitionStatus;
    
  3516.   (HooksDispatcherOnUpdate: Dispatcher).useFormState = updateFormState;
    
  3517. }
    
  3518. if (enableAsyncActions) {
    
  3519.   (HooksDispatcherOnUpdate: Dispatcher).useOptimistic = updateOptimistic;
    
  3520. }
    
  3521. 
    
  3522. const HooksDispatcherOnRerender: Dispatcher = {
    
  3523.   readContext,
    
  3524. 
    
  3525.   use,
    
  3526.   useCallback: updateCallback,
    
  3527.   useContext: readContext,
    
  3528.   useEffect: updateEffect,
    
  3529.   useImperativeHandle: updateImperativeHandle,
    
  3530.   useInsertionEffect: updateInsertionEffect,
    
  3531.   useLayoutEffect: updateLayoutEffect,
    
  3532.   useMemo: updateMemo,
    
  3533.   useReducer: rerenderReducer,
    
  3534.   useRef: updateRef,
    
  3535.   useState: rerenderState,
    
  3536.   useDebugValue: updateDebugValue,
    
  3537.   useDeferredValue: rerenderDeferredValue,
    
  3538.   useTransition: rerenderTransition,
    
  3539.   useSyncExternalStore: updateSyncExternalStore,
    
  3540.   useId: updateId,
    
  3541. };
    
  3542. if (enableCache) {
    
  3543.   (HooksDispatcherOnRerender: Dispatcher).useCacheRefresh = updateRefresh;
    
  3544. }
    
  3545. if (enableUseMemoCacheHook) {
    
  3546.   (HooksDispatcherOnRerender: Dispatcher).useMemoCache = useMemoCache;
    
  3547. }
    
  3548. if (enableUseEffectEventHook) {
    
  3549.   (HooksDispatcherOnRerender: Dispatcher).useEffectEvent = updateEvent;
    
  3550. }
    
  3551. if (enableFormActions && enableAsyncActions) {
    
  3552.   (HooksDispatcherOnRerender: Dispatcher).useHostTransitionStatus =
    
  3553.     useHostTransitionStatus;
    
  3554.   (HooksDispatcherOnRerender: Dispatcher).useFormState = rerenderFormState;
    
  3555. }
    
  3556. if (enableAsyncActions) {
    
  3557.   (HooksDispatcherOnRerender: Dispatcher).useOptimistic = rerenderOptimistic;
    
  3558. }
    
  3559. 
    
  3560. let HooksDispatcherOnMountInDEV: Dispatcher | null = null;
    
  3561. let HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher | null = null;
    
  3562. let HooksDispatcherOnUpdateInDEV: Dispatcher | null = null;
    
  3563. let HooksDispatcherOnRerenderInDEV: Dispatcher | null = null;
    
  3564. let InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher | null = null;
    
  3565. let InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher | null = null;
    
  3566. let InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher | null = null;
    
  3567. 
    
  3568. if (__DEV__) {
    
  3569.   const warnInvalidContextAccess = () => {
    
  3570.     console.error(
    
  3571.       'Context can only be read while React is rendering. ' +
    
  3572.         'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
    
  3573.         'In function components, you can read it directly in the function body, but not ' +
    
  3574.         'inside Hooks like useReducer() or useMemo().',
    
  3575.     );
    
  3576.   };
    
  3577. 
    
  3578.   const warnInvalidHookAccess = () => {
    
  3579.     console.error(
    
  3580.       'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +
    
  3581.         'You can only call Hooks at the top level of your React function. ' +
    
  3582.         'For more information, see ' +
    
  3583.         'https://reactjs.org/link/rules-of-hooks',
    
  3584.     );
    
  3585.   };
    
  3586. 
    
  3587.   HooksDispatcherOnMountInDEV = {
    
  3588.     readContext<T>(context: ReactContext<T>): T {
    
  3589.       return readContext(context);
    
  3590.     },
    
  3591.     use,
    
  3592.     useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
    
  3593.       currentHookNameInDev = 'useCallback';
    
  3594.       mountHookTypesDev();
    
  3595.       checkDepsAreArrayDev(deps);
    
  3596.       return mountCallback(callback, deps);
    
  3597.     },
    
  3598.     useContext<T>(context: ReactContext<T>): T {
    
  3599.       currentHookNameInDev = 'useContext';
    
  3600.       mountHookTypesDev();
    
  3601.       return readContext(context);
    
  3602.     },
    
  3603.     useEffect(
    
  3604.       create: () => (() => void) | void,
    
  3605.       deps: Array<mixed> | void | null,
    
  3606.     ): void {
    
  3607.       currentHookNameInDev = 'useEffect';
    
  3608.       mountHookTypesDev();
    
  3609.       checkDepsAreArrayDev(deps);
    
  3610.       return mountEffect(create, deps);
    
  3611.     },
    
  3612.     useImperativeHandle<T>(
    
  3613.       ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  3614.       create: () => T,
    
  3615.       deps: Array<mixed> | void | null,
    
  3616.     ): void {
    
  3617.       currentHookNameInDev = 'useImperativeHandle';
    
  3618.       mountHookTypesDev();
    
  3619.       checkDepsAreArrayDev(deps);
    
  3620.       return mountImperativeHandle(ref, create, deps);
    
  3621.     },
    
  3622.     useInsertionEffect(
    
  3623.       create: () => (() => void) | void,
    
  3624.       deps: Array<mixed> | void | null,
    
  3625.     ): void {
    
  3626.       currentHookNameInDev = 'useInsertionEffect';
    
  3627.       mountHookTypesDev();
    
  3628.       checkDepsAreArrayDev(deps);
    
  3629.       return mountInsertionEffect(create, deps);
    
  3630.     },
    
  3631.     useLayoutEffect(
    
  3632.       create: () => (() => void) | void,
    
  3633.       deps: Array<mixed> | void | null,
    
  3634.     ): void {
    
  3635.       currentHookNameInDev = 'useLayoutEffect';
    
  3636.       mountHookTypesDev();
    
  3637.       checkDepsAreArrayDev(deps);
    
  3638.       return mountLayoutEffect(create, deps);
    
  3639.     },
    
  3640.     useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {
    
  3641.       currentHookNameInDev = 'useMemo';
    
  3642.       mountHookTypesDev();
    
  3643.       checkDepsAreArrayDev(deps);
    
  3644.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  3645.       ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
    
  3646.       try {
    
  3647.         return mountMemo(create, deps);
    
  3648.       } finally {
    
  3649.         ReactCurrentDispatcher.current = prevDispatcher;
    
  3650.       }
    
  3651.     },
    
  3652.     useReducer<S, I, A>(
    
  3653.       reducer: (S, A) => S,
    
  3654.       initialArg: I,
    
  3655.       init?: I => S,
    
  3656.     ): [S, Dispatch<A>] {
    
  3657.       currentHookNameInDev = 'useReducer';
    
  3658.       mountHookTypesDev();
    
  3659.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  3660.       ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
    
  3661.       try {
    
  3662.         return mountReducer(reducer, initialArg, init);
    
  3663.       } finally {
    
  3664.         ReactCurrentDispatcher.current = prevDispatcher;
    
  3665.       }
    
  3666.     },
    
  3667.     useRef<T>(initialValue: T): {current: T} {
    
  3668.       currentHookNameInDev = 'useRef';
    
  3669.       mountHookTypesDev();
    
  3670.       return mountRef(initialValue);
    
  3671.     },
    
  3672.     useState<S>(
    
  3673.       initialState: (() => S) | S,
    
  3674.     ): [S, Dispatch<BasicStateAction<S>>] {
    
  3675.       currentHookNameInDev = 'useState';
    
  3676.       mountHookTypesDev();
    
  3677.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  3678.       ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
    
  3679.       try {
    
  3680.         return mountState(initialState);
    
  3681.       } finally {
    
  3682.         ReactCurrentDispatcher.current = prevDispatcher;
    
  3683.       }
    
  3684.     },
    
  3685.     useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {
    
  3686.       currentHookNameInDev = 'useDebugValue';
    
  3687.       mountHookTypesDev();
    
  3688.       return mountDebugValue(value, formatterFn);
    
  3689.     },
    
  3690.     useDeferredValue<T>(value: T, initialValue?: T): T {
    
  3691.       currentHookNameInDev = 'useDeferredValue';
    
  3692.       mountHookTypesDev();
    
  3693.       return mountDeferredValue(value, initialValue);
    
  3694.     },
    
  3695.     useTransition(): [boolean, (() => void) => void] {
    
  3696.       currentHookNameInDev = 'useTransition';
    
  3697.       mountHookTypesDev();
    
  3698.       return mountTransition();
    
  3699.     },
    
  3700.     useSyncExternalStore<T>(
    
  3701.       subscribe: (() => void) => () => void,
    
  3702.       getSnapshot: () => T,
    
  3703.       getServerSnapshot?: () => T,
    
  3704.     ): T {
    
  3705.       currentHookNameInDev = 'useSyncExternalStore';
    
  3706.       mountHookTypesDev();
    
  3707.       return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
    
  3708.     },
    
  3709.     useId(): string {
    
  3710.       currentHookNameInDev = 'useId';
    
  3711.       mountHookTypesDev();
    
  3712.       return mountId();
    
  3713.     },
    
  3714.   };
    
  3715.   if (enableCache) {
    
  3716.     (HooksDispatcherOnMountInDEV: Dispatcher).useCacheRefresh =
    
  3717.       function useCacheRefresh() {
    
  3718.         currentHookNameInDev = 'useCacheRefresh';
    
  3719.         mountHookTypesDev();
    
  3720.         return mountRefresh();
    
  3721.       };
    
  3722.   }
    
  3723.   if (enableUseMemoCacheHook) {
    
  3724.     (HooksDispatcherOnMountInDEV: Dispatcher).useMemoCache = useMemoCache;
    
  3725.   }
    
  3726.   if (enableUseEffectEventHook) {
    
  3727.     (HooksDispatcherOnMountInDEV: Dispatcher).useEffectEvent =
    
  3728.       function useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(
    
  3729.         callback: F,
    
  3730.       ): F {
    
  3731.         currentHookNameInDev = 'useEffectEvent';
    
  3732.         mountHookTypesDev();
    
  3733.         return mountEvent(callback);
    
  3734.       };
    
  3735.   }
    
  3736.   if (enableFormActions && enableAsyncActions) {
    
  3737.     (HooksDispatcherOnMountInDEV: Dispatcher).useHostTransitionStatus =
    
  3738.       useHostTransitionStatus;
    
  3739.     (HooksDispatcherOnMountInDEV: Dispatcher).useFormState =
    
  3740.       function useFormState<S, P>(
    
  3741.         action: (Awaited<S>, P) => S,
    
  3742.         initialState: Awaited<S>,
    
  3743.         permalink?: string,
    
  3744.       ): [Awaited<S>, (P) => void] {
    
  3745.         currentHookNameInDev = 'useFormState';
    
  3746.         mountHookTypesDev();
    
  3747.         return mountFormState(action, initialState, permalink);
    
  3748.       };
    
  3749.   }
    
  3750.   if (enableAsyncActions) {
    
  3751.     (HooksDispatcherOnMountInDEV: Dispatcher).useOptimistic =
    
  3752.       function useOptimistic<S, A>(
    
  3753.         passthrough: S,
    
  3754.         reducer: ?(S, A) => S,
    
  3755.       ): [S, (A) => void] {
    
  3756.         currentHookNameInDev = 'useOptimistic';
    
  3757.         mountHookTypesDev();
    
  3758.         return mountOptimistic(passthrough, reducer);
    
  3759.       };
    
  3760.   }
    
  3761. 
    
  3762.   HooksDispatcherOnMountWithHookTypesInDEV = {
    
  3763.     readContext<T>(context: ReactContext<T>): T {
    
  3764.       return readContext(context);
    
  3765.     },
    
  3766.     use,
    
  3767.     useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
    
  3768.       currentHookNameInDev = 'useCallback';
    
  3769.       updateHookTypesDev();
    
  3770.       return mountCallback(callback, deps);
    
  3771.     },
    
  3772.     useContext<T>(context: ReactContext<T>): T {
    
  3773.       currentHookNameInDev = 'useContext';
    
  3774.       updateHookTypesDev();
    
  3775.       return readContext(context);
    
  3776.     },
    
  3777.     useEffect(
    
  3778.       create: () => (() => void) | void,
    
  3779.       deps: Array<mixed> | void | null,
    
  3780.     ): void {
    
  3781.       currentHookNameInDev = 'useEffect';
    
  3782.       updateHookTypesDev();
    
  3783.       return mountEffect(create, deps);
    
  3784.     },
    
  3785.     useImperativeHandle<T>(
    
  3786.       ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  3787.       create: () => T,
    
  3788.       deps: Array<mixed> | void | null,
    
  3789.     ): void {
    
  3790.       currentHookNameInDev = 'useImperativeHandle';
    
  3791.       updateHookTypesDev();
    
  3792.       return mountImperativeHandle(ref, create, deps);
    
  3793.     },
    
  3794.     useInsertionEffect(
    
  3795.       create: () => (() => void) | void,
    
  3796.       deps: Array<mixed> | void | null,
    
  3797.     ): void {
    
  3798.       currentHookNameInDev = 'useInsertionEffect';
    
  3799.       updateHookTypesDev();
    
  3800.       return mountInsertionEffect(create, deps);
    
  3801.     },
    
  3802.     useLayoutEffect(
    
  3803.       create: () => (() => void) | void,
    
  3804.       deps: Array<mixed> | void | null,
    
  3805.     ): void {
    
  3806.       currentHookNameInDev = 'useLayoutEffect';
    
  3807.       updateHookTypesDev();
    
  3808.       return mountLayoutEffect(create, deps);
    
  3809.     },
    
  3810.     useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {
    
  3811.       currentHookNameInDev = 'useMemo';
    
  3812.       updateHookTypesDev();
    
  3813.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  3814.       ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
    
  3815.       try {
    
  3816.         return mountMemo(create, deps);
    
  3817.       } finally {
    
  3818.         ReactCurrentDispatcher.current = prevDispatcher;
    
  3819.       }
    
  3820.     },
    
  3821.     useReducer<S, I, A>(
    
  3822.       reducer: (S, A) => S,
    
  3823.       initialArg: I,
    
  3824.       init?: I => S,
    
  3825.     ): [S, Dispatch<A>] {
    
  3826.       currentHookNameInDev = 'useReducer';
    
  3827.       updateHookTypesDev();
    
  3828.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  3829.       ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
    
  3830.       try {
    
  3831.         return mountReducer(reducer, initialArg, init);
    
  3832.       } finally {
    
  3833.         ReactCurrentDispatcher.current = prevDispatcher;
    
  3834.       }
    
  3835.     },
    
  3836.     useRef<T>(initialValue: T): {current: T} {
    
  3837.       currentHookNameInDev = 'useRef';
    
  3838.       updateHookTypesDev();
    
  3839.       return mountRef(initialValue);
    
  3840.     },
    
  3841.     useState<S>(
    
  3842.       initialState: (() => S) | S,
    
  3843.     ): [S, Dispatch<BasicStateAction<S>>] {
    
  3844.       currentHookNameInDev = 'useState';
    
  3845.       updateHookTypesDev();
    
  3846.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  3847.       ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
    
  3848.       try {
    
  3849.         return mountState(initialState);
    
  3850.       } finally {
    
  3851.         ReactCurrentDispatcher.current = prevDispatcher;
    
  3852.       }
    
  3853.     },
    
  3854.     useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {
    
  3855.       currentHookNameInDev = 'useDebugValue';
    
  3856.       updateHookTypesDev();
    
  3857.       return mountDebugValue(value, formatterFn);
    
  3858.     },
    
  3859.     useDeferredValue<T>(value: T, initialValue?: T): T {
    
  3860.       currentHookNameInDev = 'useDeferredValue';
    
  3861.       updateHookTypesDev();
    
  3862.       return mountDeferredValue(value, initialValue);
    
  3863.     },
    
  3864.     useTransition(): [boolean, (() => void) => void] {
    
  3865.       currentHookNameInDev = 'useTransition';
    
  3866.       updateHookTypesDev();
    
  3867.       return mountTransition();
    
  3868.     },
    
  3869.     useSyncExternalStore<T>(
    
  3870.       subscribe: (() => void) => () => void,
    
  3871.       getSnapshot: () => T,
    
  3872.       getServerSnapshot?: () => T,
    
  3873.     ): T {
    
  3874.       currentHookNameInDev = 'useSyncExternalStore';
    
  3875.       updateHookTypesDev();
    
  3876.       return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
    
  3877.     },
    
  3878.     useId(): string {
    
  3879.       currentHookNameInDev = 'useId';
    
  3880.       updateHookTypesDev();
    
  3881.       return mountId();
    
  3882.     },
    
  3883.   };
    
  3884.   if (enableCache) {
    
  3885.     (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useCacheRefresh =
    
  3886.       function useCacheRefresh() {
    
  3887.         currentHookNameInDev = 'useCacheRefresh';
    
  3888.         updateHookTypesDev();
    
  3889.         return mountRefresh();
    
  3890.       };
    
  3891.   }
    
  3892.   if (enableUseMemoCacheHook) {
    
  3893.     (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useMemoCache =
    
  3894.       useMemoCache;
    
  3895.   }
    
  3896.   if (enableUseEffectEventHook) {
    
  3897.     (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useEffectEvent =
    
  3898.       function useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(
    
  3899.         callback: F,
    
  3900.       ): F {
    
  3901.         currentHookNameInDev = 'useEffectEvent';
    
  3902.         updateHookTypesDev();
    
  3903.         return mountEvent(callback);
    
  3904.       };
    
  3905.   }
    
  3906.   if (enableFormActions && enableAsyncActions) {
    
  3907.     (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useHostTransitionStatus =
    
  3908.       useHostTransitionStatus;
    
  3909.     (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useFormState =
    
  3910.       function useFormState<S, P>(
    
  3911.         action: (Awaited<S>, P) => S,
    
  3912.         initialState: Awaited<S>,
    
  3913.         permalink?: string,
    
  3914.       ): [Awaited<S>, (P) => void] {
    
  3915.         currentHookNameInDev = 'useFormState';
    
  3916.         updateHookTypesDev();
    
  3917.         return mountFormState(action, initialState, permalink);
    
  3918.       };
    
  3919.   }
    
  3920.   if (enableAsyncActions) {
    
  3921.     (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useOptimistic =
    
  3922.       function useOptimistic<S, A>(
    
  3923.         passthrough: S,
    
  3924.         reducer: ?(S, A) => S,
    
  3925.       ): [S, (A) => void] {
    
  3926.         currentHookNameInDev = 'useOptimistic';
    
  3927.         updateHookTypesDev();
    
  3928.         return mountOptimistic(passthrough, reducer);
    
  3929.       };
    
  3930.   }
    
  3931. 
    
  3932.   HooksDispatcherOnUpdateInDEV = {
    
  3933.     readContext<T>(context: ReactContext<T>): T {
    
  3934.       return readContext(context);
    
  3935.     },
    
  3936.     use,
    
  3937.     useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
    
  3938.       currentHookNameInDev = 'useCallback';
    
  3939.       updateHookTypesDev();
    
  3940.       return updateCallback(callback, deps);
    
  3941.     },
    
  3942.     useContext<T>(context: ReactContext<T>): T {
    
  3943.       currentHookNameInDev = 'useContext';
    
  3944.       updateHookTypesDev();
    
  3945.       return readContext(context);
    
  3946.     },
    
  3947.     useEffect(
    
  3948.       create: () => (() => void) | void,
    
  3949.       deps: Array<mixed> | void | null,
    
  3950.     ): void {
    
  3951.       currentHookNameInDev = 'useEffect';
    
  3952.       updateHookTypesDev();
    
  3953.       return updateEffect(create, deps);
    
  3954.     },
    
  3955.     useImperativeHandle<T>(
    
  3956.       ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  3957.       create: () => T,
    
  3958.       deps: Array<mixed> | void | null,
    
  3959.     ): void {
    
  3960.       currentHookNameInDev = 'useImperativeHandle';
    
  3961.       updateHookTypesDev();
    
  3962.       return updateImperativeHandle(ref, create, deps);
    
  3963.     },
    
  3964.     useInsertionEffect(
    
  3965.       create: () => (() => void) | void,
    
  3966.       deps: Array<mixed> | void | null,
    
  3967.     ): void {
    
  3968.       currentHookNameInDev = 'useInsertionEffect';
    
  3969.       updateHookTypesDev();
    
  3970.       return updateInsertionEffect(create, deps);
    
  3971.     },
    
  3972.     useLayoutEffect(
    
  3973.       create: () => (() => void) | void,
    
  3974.       deps: Array<mixed> | void | null,
    
  3975.     ): void {
    
  3976.       currentHookNameInDev = 'useLayoutEffect';
    
  3977.       updateHookTypesDev();
    
  3978.       return updateLayoutEffect(create, deps);
    
  3979.     },
    
  3980.     useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {
    
  3981.       currentHookNameInDev = 'useMemo';
    
  3982.       updateHookTypesDev();
    
  3983.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  3984.       ReactCurrentDispatcher.current =
    
  3985.         InvalidNestedHooksDispatcherOnUpdateInDEV;
    
  3986.       try {
    
  3987.         return updateMemo(create, deps);
    
  3988.       } finally {
    
  3989.         ReactCurrentDispatcher.current = prevDispatcher;
    
  3990.       }
    
  3991.     },
    
  3992.     useReducer<S, I, A>(
    
  3993.       reducer: (S, A) => S,
    
  3994.       initialArg: I,
    
  3995.       init?: I => S,
    
  3996.     ): [S, Dispatch<A>] {
    
  3997.       currentHookNameInDev = 'useReducer';
    
  3998.       updateHookTypesDev();
    
  3999.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4000.       ReactCurrentDispatcher.current =
    
  4001.         InvalidNestedHooksDispatcherOnUpdateInDEV;
    
  4002.       try {
    
  4003.         return updateReducer(reducer, initialArg, init);
    
  4004.       } finally {
    
  4005.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4006.       }
    
  4007.     },
    
  4008.     useRef<T>(initialValue: T): {current: T} {
    
  4009.       currentHookNameInDev = 'useRef';
    
  4010.       updateHookTypesDev();
    
  4011.       return updateRef(initialValue);
    
  4012.     },
    
  4013.     useState<S>(
    
  4014.       initialState: (() => S) | S,
    
  4015.     ): [S, Dispatch<BasicStateAction<S>>] {
    
  4016.       currentHookNameInDev = 'useState';
    
  4017.       updateHookTypesDev();
    
  4018.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4019.       ReactCurrentDispatcher.current =
    
  4020.         InvalidNestedHooksDispatcherOnUpdateInDEV;
    
  4021.       try {
    
  4022.         return updateState(initialState);
    
  4023.       } finally {
    
  4024.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4025.       }
    
  4026.     },
    
  4027.     useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {
    
  4028.       currentHookNameInDev = 'useDebugValue';
    
  4029.       updateHookTypesDev();
    
  4030.       return updateDebugValue(value, formatterFn);
    
  4031.     },
    
  4032.     useDeferredValue<T>(value: T, initialValue?: T): T {
    
  4033.       currentHookNameInDev = 'useDeferredValue';
    
  4034.       updateHookTypesDev();
    
  4035.       return updateDeferredValue(value, initialValue);
    
  4036.     },
    
  4037.     useTransition(): [boolean, (() => void) => void] {
    
  4038.       currentHookNameInDev = 'useTransition';
    
  4039.       updateHookTypesDev();
    
  4040.       return updateTransition();
    
  4041.     },
    
  4042.     useSyncExternalStore<T>(
    
  4043.       subscribe: (() => void) => () => void,
    
  4044.       getSnapshot: () => T,
    
  4045.       getServerSnapshot?: () => T,
    
  4046.     ): T {
    
  4047.       currentHookNameInDev = 'useSyncExternalStore';
    
  4048.       updateHookTypesDev();
    
  4049.       return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
    
  4050.     },
    
  4051.     useId(): string {
    
  4052.       currentHookNameInDev = 'useId';
    
  4053.       updateHookTypesDev();
    
  4054.       return updateId();
    
  4055.     },
    
  4056.   };
    
  4057.   if (enableCache) {
    
  4058.     (HooksDispatcherOnUpdateInDEV: Dispatcher).useCacheRefresh =
    
  4059.       function useCacheRefresh() {
    
  4060.         currentHookNameInDev = 'useCacheRefresh';
    
  4061.         updateHookTypesDev();
    
  4062.         return updateRefresh();
    
  4063.       };
    
  4064.   }
    
  4065.   if (enableUseMemoCacheHook) {
    
  4066.     (HooksDispatcherOnUpdateInDEV: Dispatcher).useMemoCache = useMemoCache;
    
  4067.   }
    
  4068.   if (enableUseEffectEventHook) {
    
  4069.     (HooksDispatcherOnUpdateInDEV: Dispatcher).useEffectEvent =
    
  4070.       function useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(
    
  4071.         callback: F,
    
  4072.       ): F {
    
  4073.         currentHookNameInDev = 'useEffectEvent';
    
  4074.         updateHookTypesDev();
    
  4075.         return updateEvent(callback);
    
  4076.       };
    
  4077.   }
    
  4078.   if (enableFormActions && enableAsyncActions) {
    
  4079.     (HooksDispatcherOnUpdateInDEV: Dispatcher).useHostTransitionStatus =
    
  4080.       useHostTransitionStatus;
    
  4081.     (HooksDispatcherOnUpdateInDEV: Dispatcher).useFormState =
    
  4082.       function useFormState<S, P>(
    
  4083.         action: (Awaited<S>, P) => S,
    
  4084.         initialState: Awaited<S>,
    
  4085.         permalink?: string,
    
  4086.       ): [Awaited<S>, (P) => void] {
    
  4087.         currentHookNameInDev = 'useFormState';
    
  4088.         updateHookTypesDev();
    
  4089.         return updateFormState(action, initialState, permalink);
    
  4090.       };
    
  4091.   }
    
  4092.   if (enableAsyncActions) {
    
  4093.     (HooksDispatcherOnUpdateInDEV: Dispatcher).useOptimistic =
    
  4094.       function useOptimistic<S, A>(
    
  4095.         passthrough: S,
    
  4096.         reducer: ?(S, A) => S,
    
  4097.       ): [S, (A) => void] {
    
  4098.         currentHookNameInDev = 'useOptimistic';
    
  4099.         updateHookTypesDev();
    
  4100.         return updateOptimistic(passthrough, reducer);
    
  4101.       };
    
  4102.   }
    
  4103. 
    
  4104.   HooksDispatcherOnRerenderInDEV = {
    
  4105.     readContext<T>(context: ReactContext<T>): T {
    
  4106.       return readContext(context);
    
  4107.     },
    
  4108.     use,
    
  4109.     useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
    
  4110.       currentHookNameInDev = 'useCallback';
    
  4111.       updateHookTypesDev();
    
  4112.       return updateCallback(callback, deps);
    
  4113.     },
    
  4114.     useContext<T>(context: ReactContext<T>): T {
    
  4115.       currentHookNameInDev = 'useContext';
    
  4116.       updateHookTypesDev();
    
  4117.       return readContext(context);
    
  4118.     },
    
  4119.     useEffect(
    
  4120.       create: () => (() => void) | void,
    
  4121.       deps: Array<mixed> | void | null,
    
  4122.     ): void {
    
  4123.       currentHookNameInDev = 'useEffect';
    
  4124.       updateHookTypesDev();
    
  4125.       return updateEffect(create, deps);
    
  4126.     },
    
  4127.     useImperativeHandle<T>(
    
  4128.       ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  4129.       create: () => T,
    
  4130.       deps: Array<mixed> | void | null,
    
  4131.     ): void {
    
  4132.       currentHookNameInDev = 'useImperativeHandle';
    
  4133.       updateHookTypesDev();
    
  4134.       return updateImperativeHandle(ref, create, deps);
    
  4135.     },
    
  4136.     useInsertionEffect(
    
  4137.       create: () => (() => void) | void,
    
  4138.       deps: Array<mixed> | void | null,
    
  4139.     ): void {
    
  4140.       currentHookNameInDev = 'useInsertionEffect';
    
  4141.       updateHookTypesDev();
    
  4142.       return updateInsertionEffect(create, deps);
    
  4143.     },
    
  4144.     useLayoutEffect(
    
  4145.       create: () => (() => void) | void,
    
  4146.       deps: Array<mixed> | void | null,
    
  4147.     ): void {
    
  4148.       currentHookNameInDev = 'useLayoutEffect';
    
  4149.       updateHookTypesDev();
    
  4150.       return updateLayoutEffect(create, deps);
    
  4151.     },
    
  4152.     useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {
    
  4153.       currentHookNameInDev = 'useMemo';
    
  4154.       updateHookTypesDev();
    
  4155.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4156.       ReactCurrentDispatcher.current =
    
  4157.         InvalidNestedHooksDispatcherOnRerenderInDEV;
    
  4158.       try {
    
  4159.         return updateMemo(create, deps);
    
  4160.       } finally {
    
  4161.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4162.       }
    
  4163.     },
    
  4164.     useReducer<S, I, A>(
    
  4165.       reducer: (S, A) => S,
    
  4166.       initialArg: I,
    
  4167.       init?: I => S,
    
  4168.     ): [S, Dispatch<A>] {
    
  4169.       currentHookNameInDev = 'useReducer';
    
  4170.       updateHookTypesDev();
    
  4171.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4172.       ReactCurrentDispatcher.current =
    
  4173.         InvalidNestedHooksDispatcherOnRerenderInDEV;
    
  4174.       try {
    
  4175.         return rerenderReducer(reducer, initialArg, init);
    
  4176.       } finally {
    
  4177.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4178.       }
    
  4179.     },
    
  4180.     useRef<T>(initialValue: T): {current: T} {
    
  4181.       currentHookNameInDev = 'useRef';
    
  4182.       updateHookTypesDev();
    
  4183.       return updateRef(initialValue);
    
  4184.     },
    
  4185.     useState<S>(
    
  4186.       initialState: (() => S) | S,
    
  4187.     ): [S, Dispatch<BasicStateAction<S>>] {
    
  4188.       currentHookNameInDev = 'useState';
    
  4189.       updateHookTypesDev();
    
  4190.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4191.       ReactCurrentDispatcher.current =
    
  4192.         InvalidNestedHooksDispatcherOnRerenderInDEV;
    
  4193.       try {
    
  4194.         return rerenderState(initialState);
    
  4195.       } finally {
    
  4196.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4197.       }
    
  4198.     },
    
  4199.     useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {
    
  4200.       currentHookNameInDev = 'useDebugValue';
    
  4201.       updateHookTypesDev();
    
  4202.       return updateDebugValue(value, formatterFn);
    
  4203.     },
    
  4204.     useDeferredValue<T>(value: T, initialValue?: T): T {
    
  4205.       currentHookNameInDev = 'useDeferredValue';
    
  4206.       updateHookTypesDev();
    
  4207.       return rerenderDeferredValue(value, initialValue);
    
  4208.     },
    
  4209.     useTransition(): [boolean, (() => void) => void] {
    
  4210.       currentHookNameInDev = 'useTransition';
    
  4211.       updateHookTypesDev();
    
  4212.       return rerenderTransition();
    
  4213.     },
    
  4214.     useSyncExternalStore<T>(
    
  4215.       subscribe: (() => void) => () => void,
    
  4216.       getSnapshot: () => T,
    
  4217.       getServerSnapshot?: () => T,
    
  4218.     ): T {
    
  4219.       currentHookNameInDev = 'useSyncExternalStore';
    
  4220.       updateHookTypesDev();
    
  4221.       return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
    
  4222.     },
    
  4223.     useId(): string {
    
  4224.       currentHookNameInDev = 'useId';
    
  4225.       updateHookTypesDev();
    
  4226.       return updateId();
    
  4227.     },
    
  4228.   };
    
  4229.   if (enableCache) {
    
  4230.     (HooksDispatcherOnRerenderInDEV: Dispatcher).useCacheRefresh =
    
  4231.       function useCacheRefresh() {
    
  4232.         currentHookNameInDev = 'useCacheRefresh';
    
  4233.         updateHookTypesDev();
    
  4234.         return updateRefresh();
    
  4235.       };
    
  4236.   }
    
  4237.   if (enableUseMemoCacheHook) {
    
  4238.     (HooksDispatcherOnRerenderInDEV: Dispatcher).useMemoCache = useMemoCache;
    
  4239.   }
    
  4240.   if (enableUseEffectEventHook) {
    
  4241.     (HooksDispatcherOnRerenderInDEV: Dispatcher).useEffectEvent =
    
  4242.       function useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(
    
  4243.         callback: F,
    
  4244.       ): F {
    
  4245.         currentHookNameInDev = 'useEffectEvent';
    
  4246.         updateHookTypesDev();
    
  4247.         return updateEvent(callback);
    
  4248.       };
    
  4249.   }
    
  4250.   if (enableFormActions && enableAsyncActions) {
    
  4251.     (HooksDispatcherOnRerenderInDEV: Dispatcher).useHostTransitionStatus =
    
  4252.       useHostTransitionStatus;
    
  4253.     (HooksDispatcherOnRerenderInDEV: Dispatcher).useFormState =
    
  4254.       function useFormState<S, P>(
    
  4255.         action: (Awaited<S>, P) => S,
    
  4256.         initialState: Awaited<S>,
    
  4257.         permalink?: string,
    
  4258.       ): [Awaited<S>, (P) => void] {
    
  4259.         currentHookNameInDev = 'useFormState';
    
  4260.         updateHookTypesDev();
    
  4261.         return rerenderFormState(action, initialState, permalink);
    
  4262.       };
    
  4263.   }
    
  4264.   if (enableAsyncActions) {
    
  4265.     (HooksDispatcherOnRerenderInDEV: Dispatcher).useOptimistic =
    
  4266.       function useOptimistic<S, A>(
    
  4267.         passthrough: S,
    
  4268.         reducer: ?(S, A) => S,
    
  4269.       ): [S, (A) => void] {
    
  4270.         currentHookNameInDev = 'useOptimistic';
    
  4271.         updateHookTypesDev();
    
  4272.         return rerenderOptimistic(passthrough, reducer);
    
  4273.       };
    
  4274.   }
    
  4275. 
    
  4276.   InvalidNestedHooksDispatcherOnMountInDEV = {
    
  4277.     readContext<T>(context: ReactContext<T>): T {
    
  4278.       warnInvalidContextAccess();
    
  4279.       return readContext(context);
    
  4280.     },
    
  4281.     use<T>(usable: Usable<T>): T {
    
  4282.       warnInvalidHookAccess();
    
  4283.       return use(usable);
    
  4284.     },
    
  4285.     useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
    
  4286.       currentHookNameInDev = 'useCallback';
    
  4287.       warnInvalidHookAccess();
    
  4288.       mountHookTypesDev();
    
  4289.       return mountCallback(callback, deps);
    
  4290.     },
    
  4291.     useContext<T>(context: ReactContext<T>): T {
    
  4292.       currentHookNameInDev = 'useContext';
    
  4293.       warnInvalidHookAccess();
    
  4294.       mountHookTypesDev();
    
  4295.       return readContext(context);
    
  4296.     },
    
  4297.     useEffect(
    
  4298.       create: () => (() => void) | void,
    
  4299.       deps: Array<mixed> | void | null,
    
  4300.     ): void {
    
  4301.       currentHookNameInDev = 'useEffect';
    
  4302.       warnInvalidHookAccess();
    
  4303.       mountHookTypesDev();
    
  4304.       return mountEffect(create, deps);
    
  4305.     },
    
  4306.     useImperativeHandle<T>(
    
  4307.       ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  4308.       create: () => T,
    
  4309.       deps: Array<mixed> | void | null,
    
  4310.     ): void {
    
  4311.       currentHookNameInDev = 'useImperativeHandle';
    
  4312.       warnInvalidHookAccess();
    
  4313.       mountHookTypesDev();
    
  4314.       return mountImperativeHandle(ref, create, deps);
    
  4315.     },
    
  4316.     useInsertionEffect(
    
  4317.       create: () => (() => void) | void,
    
  4318.       deps: Array<mixed> | void | null,
    
  4319.     ): void {
    
  4320.       currentHookNameInDev = 'useInsertionEffect';
    
  4321.       warnInvalidHookAccess();
    
  4322.       mountHookTypesDev();
    
  4323.       return mountInsertionEffect(create, deps);
    
  4324.     },
    
  4325.     useLayoutEffect(
    
  4326.       create: () => (() => void) | void,
    
  4327.       deps: Array<mixed> | void | null,
    
  4328.     ): void {
    
  4329.       currentHookNameInDev = 'useLayoutEffect';
    
  4330.       warnInvalidHookAccess();
    
  4331.       mountHookTypesDev();
    
  4332.       return mountLayoutEffect(create, deps);
    
  4333.     },
    
  4334.     useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {
    
  4335.       currentHookNameInDev = 'useMemo';
    
  4336.       warnInvalidHookAccess();
    
  4337.       mountHookTypesDev();
    
  4338.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4339.       ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
    
  4340.       try {
    
  4341.         return mountMemo(create, deps);
    
  4342.       } finally {
    
  4343.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4344.       }
    
  4345.     },
    
  4346.     useReducer<S, I, A>(
    
  4347.       reducer: (S, A) => S,
    
  4348.       initialArg: I,
    
  4349.       init?: I => S,
    
  4350.     ): [S, Dispatch<A>] {
    
  4351.       currentHookNameInDev = 'useReducer';
    
  4352.       warnInvalidHookAccess();
    
  4353.       mountHookTypesDev();
    
  4354.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4355.       ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
    
  4356.       try {
    
  4357.         return mountReducer(reducer, initialArg, init);
    
  4358.       } finally {
    
  4359.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4360.       }
    
  4361.     },
    
  4362.     useRef<T>(initialValue: T): {current: T} {
    
  4363.       currentHookNameInDev = 'useRef';
    
  4364.       warnInvalidHookAccess();
    
  4365.       mountHookTypesDev();
    
  4366.       return mountRef(initialValue);
    
  4367.     },
    
  4368.     useState<S>(
    
  4369.       initialState: (() => S) | S,
    
  4370.     ): [S, Dispatch<BasicStateAction<S>>] {
    
  4371.       currentHookNameInDev = 'useState';
    
  4372.       warnInvalidHookAccess();
    
  4373.       mountHookTypesDev();
    
  4374.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4375.       ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
    
  4376.       try {
    
  4377.         return mountState(initialState);
    
  4378.       } finally {
    
  4379.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4380.       }
    
  4381.     },
    
  4382.     useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {
    
  4383.       currentHookNameInDev = 'useDebugValue';
    
  4384.       warnInvalidHookAccess();
    
  4385.       mountHookTypesDev();
    
  4386.       return mountDebugValue(value, formatterFn);
    
  4387.     },
    
  4388.     useDeferredValue<T>(value: T, initialValue?: T): T {
    
  4389.       currentHookNameInDev = 'useDeferredValue';
    
  4390.       warnInvalidHookAccess();
    
  4391.       mountHookTypesDev();
    
  4392.       return mountDeferredValue(value, initialValue);
    
  4393.     },
    
  4394.     useTransition(): [boolean, (() => void) => void] {
    
  4395.       currentHookNameInDev = 'useTransition';
    
  4396.       warnInvalidHookAccess();
    
  4397.       mountHookTypesDev();
    
  4398.       return mountTransition();
    
  4399.     },
    
  4400.     useSyncExternalStore<T>(
    
  4401.       subscribe: (() => void) => () => void,
    
  4402.       getSnapshot: () => T,
    
  4403.       getServerSnapshot?: () => T,
    
  4404.     ): T {
    
  4405.       currentHookNameInDev = 'useSyncExternalStore';
    
  4406.       warnInvalidHookAccess();
    
  4407.       mountHookTypesDev();
    
  4408.       return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
    
  4409.     },
    
  4410.     useId(): string {
    
  4411.       currentHookNameInDev = 'useId';
    
  4412.       warnInvalidHookAccess();
    
  4413.       mountHookTypesDev();
    
  4414.       return mountId();
    
  4415.     },
    
  4416.   };
    
  4417.   if (enableCache) {
    
  4418.     (InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).useCacheRefresh =
    
  4419.       function useCacheRefresh() {
    
  4420.         currentHookNameInDev = 'useCacheRefresh';
    
  4421.         mountHookTypesDev();
    
  4422.         return mountRefresh();
    
  4423.       };
    
  4424.   }
    
  4425.   if (enableUseMemoCacheHook) {
    
  4426.     (InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).useMemoCache =
    
  4427.       function (size: number): Array<any> {
    
  4428.         warnInvalidHookAccess();
    
  4429.         return useMemoCache(size);
    
  4430.       };
    
  4431.   }
    
  4432.   if (enableUseEffectEventHook) {
    
  4433.     (InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).useEffectEvent =
    
  4434.       function useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(
    
  4435.         callback: F,
    
  4436.       ): F {
    
  4437.         currentHookNameInDev = 'useEffectEvent';
    
  4438.         warnInvalidHookAccess();
    
  4439.         mountHookTypesDev();
    
  4440.         return mountEvent(callback);
    
  4441.       };
    
  4442.   }
    
  4443.   if (enableFormActions && enableAsyncActions) {
    
  4444.     (InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).useHostTransitionStatus =
    
  4445.       useHostTransitionStatus;
    
  4446.     (InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).useFormState =
    
  4447.       function useFormState<S, P>(
    
  4448.         action: (Awaited<S>, P) => S,
    
  4449.         initialState: Awaited<S>,
    
  4450.         permalink?: string,
    
  4451.       ): [Awaited<S>, (P) => void] {
    
  4452.         currentHookNameInDev = 'useFormState';
    
  4453.         warnInvalidHookAccess();
    
  4454.         mountHookTypesDev();
    
  4455.         return mountFormState(action, initialState, permalink);
    
  4456.       };
    
  4457.   }
    
  4458.   if (enableAsyncActions) {
    
  4459.     (InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).useOptimistic =
    
  4460.       function useOptimistic<S, A>(
    
  4461.         passthrough: S,
    
  4462.         reducer: ?(S, A) => S,
    
  4463.       ): [S, (A) => void] {
    
  4464.         currentHookNameInDev = 'useOptimistic';
    
  4465.         warnInvalidHookAccess();
    
  4466.         mountHookTypesDev();
    
  4467.         return mountOptimistic(passthrough, reducer);
    
  4468.       };
    
  4469.   }
    
  4470. 
    
  4471.   InvalidNestedHooksDispatcherOnUpdateInDEV = {
    
  4472.     readContext<T>(context: ReactContext<T>): T {
    
  4473.       warnInvalidContextAccess();
    
  4474.       return readContext(context);
    
  4475.     },
    
  4476.     use<T>(usable: Usable<T>): T {
    
  4477.       warnInvalidHookAccess();
    
  4478.       return use(usable);
    
  4479.     },
    
  4480.     useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
    
  4481.       currentHookNameInDev = 'useCallback';
    
  4482.       warnInvalidHookAccess();
    
  4483.       updateHookTypesDev();
    
  4484.       return updateCallback(callback, deps);
    
  4485.     },
    
  4486.     useContext<T>(context: ReactContext<T>): T {
    
  4487.       currentHookNameInDev = 'useContext';
    
  4488.       warnInvalidHookAccess();
    
  4489.       updateHookTypesDev();
    
  4490.       return readContext(context);
    
  4491.     },
    
  4492.     useEffect(
    
  4493.       create: () => (() => void) | void,
    
  4494.       deps: Array<mixed> | void | null,
    
  4495.     ): void {
    
  4496.       currentHookNameInDev = 'useEffect';
    
  4497.       warnInvalidHookAccess();
    
  4498.       updateHookTypesDev();
    
  4499.       return updateEffect(create, deps);
    
  4500.     },
    
  4501.     useImperativeHandle<T>(
    
  4502.       ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  4503.       create: () => T,
    
  4504.       deps: Array<mixed> | void | null,
    
  4505.     ): void {
    
  4506.       currentHookNameInDev = 'useImperativeHandle';
    
  4507.       warnInvalidHookAccess();
    
  4508.       updateHookTypesDev();
    
  4509.       return updateImperativeHandle(ref, create, deps);
    
  4510.     },
    
  4511.     useInsertionEffect(
    
  4512.       create: () => (() => void) | void,
    
  4513.       deps: Array<mixed> | void | null,
    
  4514.     ): void {
    
  4515.       currentHookNameInDev = 'useInsertionEffect';
    
  4516.       warnInvalidHookAccess();
    
  4517.       updateHookTypesDev();
    
  4518.       return updateInsertionEffect(create, deps);
    
  4519.     },
    
  4520.     useLayoutEffect(
    
  4521.       create: () => (() => void) | void,
    
  4522.       deps: Array<mixed> | void | null,
    
  4523.     ): void {
    
  4524.       currentHookNameInDev = 'useLayoutEffect';
    
  4525.       warnInvalidHookAccess();
    
  4526.       updateHookTypesDev();
    
  4527.       return updateLayoutEffect(create, deps);
    
  4528.     },
    
  4529.     useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {
    
  4530.       currentHookNameInDev = 'useMemo';
    
  4531.       warnInvalidHookAccess();
    
  4532.       updateHookTypesDev();
    
  4533.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4534.       ReactCurrentDispatcher.current =
    
  4535.         InvalidNestedHooksDispatcherOnUpdateInDEV;
    
  4536.       try {
    
  4537.         return updateMemo(create, deps);
    
  4538.       } finally {
    
  4539.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4540.       }
    
  4541.     },
    
  4542.     useReducer<S, I, A>(
    
  4543.       reducer: (S, A) => S,
    
  4544.       initialArg: I,
    
  4545.       init?: I => S,
    
  4546.     ): [S, Dispatch<A>] {
    
  4547.       currentHookNameInDev = 'useReducer';
    
  4548.       warnInvalidHookAccess();
    
  4549.       updateHookTypesDev();
    
  4550.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4551.       ReactCurrentDispatcher.current =
    
  4552.         InvalidNestedHooksDispatcherOnUpdateInDEV;
    
  4553.       try {
    
  4554.         return updateReducer(reducer, initialArg, init);
    
  4555.       } finally {
    
  4556.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4557.       }
    
  4558.     },
    
  4559.     useRef<T>(initialValue: T): {current: T} {
    
  4560.       currentHookNameInDev = 'useRef';
    
  4561.       warnInvalidHookAccess();
    
  4562.       updateHookTypesDev();
    
  4563.       return updateRef(initialValue);
    
  4564.     },
    
  4565.     useState<S>(
    
  4566.       initialState: (() => S) | S,
    
  4567.     ): [S, Dispatch<BasicStateAction<S>>] {
    
  4568.       currentHookNameInDev = 'useState';
    
  4569.       warnInvalidHookAccess();
    
  4570.       updateHookTypesDev();
    
  4571.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4572.       ReactCurrentDispatcher.current =
    
  4573.         InvalidNestedHooksDispatcherOnUpdateInDEV;
    
  4574.       try {
    
  4575.         return updateState(initialState);
    
  4576.       } finally {
    
  4577.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4578.       }
    
  4579.     },
    
  4580.     useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {
    
  4581.       currentHookNameInDev = 'useDebugValue';
    
  4582.       warnInvalidHookAccess();
    
  4583.       updateHookTypesDev();
    
  4584.       return updateDebugValue(value, formatterFn);
    
  4585.     },
    
  4586.     useDeferredValue<T>(value: T, initialValue?: T): T {
    
  4587.       currentHookNameInDev = 'useDeferredValue';
    
  4588.       warnInvalidHookAccess();
    
  4589.       updateHookTypesDev();
    
  4590.       return updateDeferredValue(value, initialValue);
    
  4591.     },
    
  4592.     useTransition(): [boolean, (() => void) => void] {
    
  4593.       currentHookNameInDev = 'useTransition';
    
  4594.       warnInvalidHookAccess();
    
  4595.       updateHookTypesDev();
    
  4596.       return updateTransition();
    
  4597.     },
    
  4598.     useSyncExternalStore<T>(
    
  4599.       subscribe: (() => void) => () => void,
    
  4600.       getSnapshot: () => T,
    
  4601.       getServerSnapshot?: () => T,
    
  4602.     ): T {
    
  4603.       currentHookNameInDev = 'useSyncExternalStore';
    
  4604.       warnInvalidHookAccess();
    
  4605.       updateHookTypesDev();
    
  4606.       return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
    
  4607.     },
    
  4608.     useId(): string {
    
  4609.       currentHookNameInDev = 'useId';
    
  4610.       warnInvalidHookAccess();
    
  4611.       updateHookTypesDev();
    
  4612.       return updateId();
    
  4613.     },
    
  4614.   };
    
  4615.   if (enableCache) {
    
  4616.     (InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).useCacheRefresh =
    
  4617.       function useCacheRefresh() {
    
  4618.         currentHookNameInDev = 'useCacheRefresh';
    
  4619.         updateHookTypesDev();
    
  4620.         return updateRefresh();
    
  4621.       };
    
  4622.   }
    
  4623.   if (enableUseMemoCacheHook) {
    
  4624.     (InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).useMemoCache =
    
  4625.       function (size: number): Array<any> {
    
  4626.         warnInvalidHookAccess();
    
  4627.         return useMemoCache(size);
    
  4628.       };
    
  4629.   }
    
  4630.   if (enableUseEffectEventHook) {
    
  4631.     (InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).useEffectEvent =
    
  4632.       function useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(
    
  4633.         callback: F,
    
  4634.       ): F {
    
  4635.         currentHookNameInDev = 'useEffectEvent';
    
  4636.         warnInvalidHookAccess();
    
  4637.         updateHookTypesDev();
    
  4638.         return updateEvent(callback);
    
  4639.       };
    
  4640.   }
    
  4641.   if (enableFormActions && enableAsyncActions) {
    
  4642.     (InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).useHostTransitionStatus =
    
  4643.       useHostTransitionStatus;
    
  4644.     (InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).useFormState =
    
  4645.       function useFormState<S, P>(
    
  4646.         action: (Awaited<S>, P) => S,
    
  4647.         initialState: Awaited<S>,
    
  4648.         permalink?: string,
    
  4649.       ): [Awaited<S>, (P) => void] {
    
  4650.         currentHookNameInDev = 'useFormState';
    
  4651.         warnInvalidHookAccess();
    
  4652.         updateHookTypesDev();
    
  4653.         return updateFormState(action, initialState, permalink);
    
  4654.       };
    
  4655.   }
    
  4656.   if (enableAsyncActions) {
    
  4657.     (InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).useOptimistic =
    
  4658.       function useOptimistic<S, A>(
    
  4659.         passthrough: S,
    
  4660.         reducer: ?(S, A) => S,
    
  4661.       ): [S, (A) => void] {
    
  4662.         currentHookNameInDev = 'useOptimistic';
    
  4663.         warnInvalidHookAccess();
    
  4664.         updateHookTypesDev();
    
  4665.         return updateOptimistic(passthrough, reducer);
    
  4666.       };
    
  4667.   }
    
  4668. 
    
  4669.   InvalidNestedHooksDispatcherOnRerenderInDEV = {
    
  4670.     readContext<T>(context: ReactContext<T>): T {
    
  4671.       warnInvalidContextAccess();
    
  4672.       return readContext(context);
    
  4673.     },
    
  4674.     use<T>(usable: Usable<T>): T {
    
  4675.       warnInvalidHookAccess();
    
  4676.       return use(usable);
    
  4677.     },
    
  4678.     useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
    
  4679.       currentHookNameInDev = 'useCallback';
    
  4680.       warnInvalidHookAccess();
    
  4681.       updateHookTypesDev();
    
  4682.       return updateCallback(callback, deps);
    
  4683.     },
    
  4684.     useContext<T>(context: ReactContext<T>): T {
    
  4685.       currentHookNameInDev = 'useContext';
    
  4686.       warnInvalidHookAccess();
    
  4687.       updateHookTypesDev();
    
  4688.       return readContext(context);
    
  4689.     },
    
  4690.     useEffect(
    
  4691.       create: () => (() => void) | void,
    
  4692.       deps: Array<mixed> | void | null,
    
  4693.     ): void {
    
  4694.       currentHookNameInDev = 'useEffect';
    
  4695.       warnInvalidHookAccess();
    
  4696.       updateHookTypesDev();
    
  4697.       return updateEffect(create, deps);
    
  4698.     },
    
  4699.     useImperativeHandle<T>(
    
  4700.       ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  4701.       create: () => T,
    
  4702.       deps: Array<mixed> | void | null,
    
  4703.     ): void {
    
  4704.       currentHookNameInDev = 'useImperativeHandle';
    
  4705.       warnInvalidHookAccess();
    
  4706.       updateHookTypesDev();
    
  4707.       return updateImperativeHandle(ref, create, deps);
    
  4708.     },
    
  4709.     useInsertionEffect(
    
  4710.       create: () => (() => void) | void,
    
  4711.       deps: Array<mixed> | void | null,
    
  4712.     ): void {
    
  4713.       currentHookNameInDev = 'useInsertionEffect';
    
  4714.       warnInvalidHookAccess();
    
  4715.       updateHookTypesDev();
    
  4716.       return updateInsertionEffect(create, deps);
    
  4717.     },
    
  4718.     useLayoutEffect(
    
  4719.       create: () => (() => void) | void,
    
  4720.       deps: Array<mixed> | void | null,
    
  4721.     ): void {
    
  4722.       currentHookNameInDev = 'useLayoutEffect';
    
  4723.       warnInvalidHookAccess();
    
  4724.       updateHookTypesDev();
    
  4725.       return updateLayoutEffect(create, deps);
    
  4726.     },
    
  4727.     useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {
    
  4728.       currentHookNameInDev = 'useMemo';
    
  4729.       warnInvalidHookAccess();
    
  4730.       updateHookTypesDev();
    
  4731.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4732.       ReactCurrentDispatcher.current =
    
  4733.         InvalidNestedHooksDispatcherOnUpdateInDEV;
    
  4734.       try {
    
  4735.         return updateMemo(create, deps);
    
  4736.       } finally {
    
  4737.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4738.       }
    
  4739.     },
    
  4740.     useReducer<S, I, A>(
    
  4741.       reducer: (S, A) => S,
    
  4742.       initialArg: I,
    
  4743.       init?: I => S,
    
  4744.     ): [S, Dispatch<A>] {
    
  4745.       currentHookNameInDev = 'useReducer';
    
  4746.       warnInvalidHookAccess();
    
  4747.       updateHookTypesDev();
    
  4748.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4749.       ReactCurrentDispatcher.current =
    
  4750.         InvalidNestedHooksDispatcherOnUpdateInDEV;
    
  4751.       try {
    
  4752.         return rerenderReducer(reducer, initialArg, init);
    
  4753.       } finally {
    
  4754.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4755.       }
    
  4756.     },
    
  4757.     useRef<T>(initialValue: T): {current: T} {
    
  4758.       currentHookNameInDev = 'useRef';
    
  4759.       warnInvalidHookAccess();
    
  4760.       updateHookTypesDev();
    
  4761.       return updateRef(initialValue);
    
  4762.     },
    
  4763.     useState<S>(
    
  4764.       initialState: (() => S) | S,
    
  4765.     ): [S, Dispatch<BasicStateAction<S>>] {
    
  4766.       currentHookNameInDev = 'useState';
    
  4767.       warnInvalidHookAccess();
    
  4768.       updateHookTypesDev();
    
  4769.       const prevDispatcher = ReactCurrentDispatcher.current;
    
  4770.       ReactCurrentDispatcher.current =
    
  4771.         InvalidNestedHooksDispatcherOnUpdateInDEV;
    
  4772.       try {
    
  4773.         return rerenderState(initialState);
    
  4774.       } finally {
    
  4775.         ReactCurrentDispatcher.current = prevDispatcher;
    
  4776.       }
    
  4777.     },
    
  4778.     useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {
    
  4779.       currentHookNameInDev = 'useDebugValue';
    
  4780.       warnInvalidHookAccess();
    
  4781.       updateHookTypesDev();
    
  4782.       return updateDebugValue(value, formatterFn);
    
  4783.     },
    
  4784.     useDeferredValue<T>(value: T, initialValue?: T): T {
    
  4785.       currentHookNameInDev = 'useDeferredValue';
    
  4786.       warnInvalidHookAccess();
    
  4787.       updateHookTypesDev();
    
  4788.       return rerenderDeferredValue(value, initialValue);
    
  4789.     },
    
  4790.     useTransition(): [boolean, (() => void) => void] {
    
  4791.       currentHookNameInDev = 'useTransition';
    
  4792.       warnInvalidHookAccess();
    
  4793.       updateHookTypesDev();
    
  4794.       return rerenderTransition();
    
  4795.     },
    
  4796.     useSyncExternalStore<T>(
    
  4797.       subscribe: (() => void) => () => void,
    
  4798.       getSnapshot: () => T,
    
  4799.       getServerSnapshot?: () => T,
    
  4800.     ): T {
    
  4801.       currentHookNameInDev = 'useSyncExternalStore';
    
  4802.       warnInvalidHookAccess();
    
  4803.       updateHookTypesDev();
    
  4804.       return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
    
  4805.     },
    
  4806.     useId(): string {
    
  4807.       currentHookNameInDev = 'useId';
    
  4808.       warnInvalidHookAccess();
    
  4809.       updateHookTypesDev();
    
  4810.       return updateId();
    
  4811.     },
    
  4812.   };
    
  4813.   if (enableCache) {
    
  4814.     (InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).useCacheRefresh =
    
  4815.       function useCacheRefresh() {
    
  4816.         currentHookNameInDev = 'useCacheRefresh';
    
  4817.         updateHookTypesDev();
    
  4818.         return updateRefresh();
    
  4819.       };
    
  4820.   }
    
  4821.   if (enableUseMemoCacheHook) {
    
  4822.     (InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).useMemoCache =
    
  4823.       function (size: number): Array<any> {
    
  4824.         warnInvalidHookAccess();
    
  4825.         return useMemoCache(size);
    
  4826.       };
    
  4827.   }
    
  4828.   if (enableUseEffectEventHook) {
    
  4829.     (InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).useEffectEvent =
    
  4830.       function useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(
    
  4831.         callback: F,
    
  4832.       ): F {
    
  4833.         currentHookNameInDev = 'useEffectEvent';
    
  4834.         warnInvalidHookAccess();
    
  4835.         updateHookTypesDev();
    
  4836.         return updateEvent(callback);
    
  4837.       };
    
  4838.   }
    
  4839.   if (enableFormActions && enableAsyncActions) {
    
  4840.     (InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).useHostTransitionStatus =
    
  4841.       useHostTransitionStatus;
    
  4842.     (InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).useFormState =
    
  4843.       function useFormState<S, P>(
    
  4844.         action: (Awaited<S>, P) => S,
    
  4845.         initialState: Awaited<S>,
    
  4846.         permalink?: string,
    
  4847.       ): [Awaited<S>, (P) => void] {
    
  4848.         currentHookNameInDev = 'useFormState';
    
  4849.         warnInvalidHookAccess();
    
  4850.         updateHookTypesDev();
    
  4851.         return rerenderFormState(action, initialState, permalink);
    
  4852.       };
    
  4853.   }
    
  4854.   if (enableAsyncActions) {
    
  4855.     (InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).useOptimistic =
    
  4856.       function useOptimistic<S, A>(
    
  4857.         passthrough: S,
    
  4858.         reducer: ?(S, A) => S,
    
  4859.       ): [S, (A) => void] {
    
  4860.         currentHookNameInDev = 'useOptimistic';
    
  4861.         warnInvalidHookAccess();
    
  4862.         updateHookTypesDev();
    
  4863.         return rerenderOptimistic(passthrough, reducer);
    
  4864.       };
    
  4865.   }
    
  4866. }