Skip to content

Commit 51c61c7

Browse files
committed
Bind startTransition to queue, not setPending
Small refactor to startTransition so that it calls setState directly instead of a bound setState method passed to it from the caller.
1 parent 409b399 commit 51c61c7

File tree

1 file changed

+44
-26
lines changed

1 file changed

+44
-26
lines changed

packages/react-reconciler/src/ReactFiberHooks.js

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,9 +1880,7 @@ function forceStoreRerender(fiber: Fiber) {
18801880
}
18811881
}
18821882

1883-
function mountState<S>(
1884-
initialState: (() => S) | S,
1885-
): [S, Dispatch<BasicStateAction<S>>] {
1883+
function mountStateImpl<S>(initialState: (() => S) | S): Hook {
18861884
const hook = mountWorkInProgressHook();
18871885
if (typeof initialState === 'function') {
18881886
// $FlowFixMe[incompatible-use]: Flow doesn't like mixed types
@@ -1897,9 +1895,20 @@ function mountState<S>(
18971895
lastRenderedState: (initialState: any),
18981896
};
18991897
hook.queue = queue;
1900-
const dispatch: Dispatch<BasicStateAction<S>> = (queue.dispatch =
1901-
(dispatchSetState.bind(null, currentlyRenderingFiber, queue): any));
1902-
return [hook.memoizedState, dispatch];
1898+
const dispatch: Dispatch<BasicStateAction<S>> = (dispatchSetState.bind(
1899+
null,
1900+
currentlyRenderingFiber,
1901+
queue,
1902+
): any);
1903+
queue.dispatch = dispatch;
1904+
return hook;
1905+
}
1906+
1907+
function mountState<S>(
1908+
initialState: (() => S) | S,
1909+
): [S, Dispatch<BasicStateAction<S>>] {
1910+
const hook = mountStateImpl(initialState);
1911+
return [hook.memoizedState, hook.queue.dispatch];
19031912
}
19041913

19051914
function updateState<S>(
@@ -2465,9 +2474,10 @@ function updateDeferredValueImpl<T>(hook: Hook, prevValue: T, value: T): T {
24652474
}
24662475

24672476
function startTransition<S>(
2477+
fiber: Fiber,
2478+
queue: UpdateQueue<S | Thenable<S>, BasicStateAction<S | Thenable<S>>>,
24682479
pendingState: S,
24692480
finishedState: S,
2470-
setPending: (Thenable<S> | S) => void,
24712481
callback: () => mixed,
24722482
options?: StartTransitionOptions,
24732483
): void {
@@ -2478,7 +2488,7 @@ function startTransition<S>(
24782488

24792489
const prevTransition = ReactCurrentBatchConfig.transition;
24802490
ReactCurrentBatchConfig.transition = null;
2481-
setPending(pendingState);
2491+
dispatchSetState(fiber, queue, pendingState);
24822492
const currentTransition = (ReactCurrentBatchConfig.transition =
24832493
({}: BatchConfigTransition));
24842494

@@ -2505,10 +2515,10 @@ function startTransition<S>(
25052515
returnValue,
25062516
finishedState,
25072517
);
2508-
setPending(maybeThenable);
2518+
dispatchSetState(fiber, queue, maybeThenable);
25092519
} else {
25102520
// Async actions are not enabled.
2511-
setPending(finishedState);
2521+
dispatchSetState(fiber, queue, finishedState);
25122522
callback();
25132523
}
25142524
} catch (error) {
@@ -2521,7 +2531,7 @@ function startTransition<S>(
25212531
status: 'rejected',
25222532
reason: error,
25232533
};
2524-
setPending(rejectedThenable);
2534+
dispatchSetState(fiber, queue, rejectedThenable);
25252535
} else {
25262536
// The error rethrowing behavior is only enabled when the async actions
25272537
// feature is on, even for sync actions.
@@ -2573,36 +2583,39 @@ export function startHostTransition<F>(
25732583
);
25742584
}
25752585

2576-
let setPending;
2586+
let queue: UpdateQueue<
2587+
Thenable<TransitionStatus> | TransitionStatus,
2588+
BasicStateAction<Thenable<TransitionStatus> | TransitionStatus>,
2589+
>;
25772590
if (formFiber.memoizedState === null) {
25782591
// Upgrade this host component fiber to be stateful. We're going to pretend
25792592
// it was stateful all along so we can reuse most of the implementation
25802593
// for function components and useTransition.
25812594
//
25822595
// Create the state hook used by TransitionAwareHostComponent. This is
25832596
// essentially an inlined version of mountState.
2584-
const queue: UpdateQueue<
2585-
Thenable<TransitionStatus> | TransitionStatus,
2597+
const newQueue: UpdateQueue<
25862598
Thenable<TransitionStatus> | TransitionStatus,
2599+
BasicStateAction<Thenable<TransitionStatus> | TransitionStatus>,
25872600
> = {
25882601
pending: null,
25892602
lanes: NoLanes,
2590-
dispatch: null,
2603+
// We're going to cheat and intentionally not create a bound dispatch
2604+
// method, because we can call it directly in startTransition.
2605+
dispatch: (null: any),
25912606
lastRenderedReducer: basicStateReducer,
25922607
lastRenderedState: NoPendingHostTransition,
25932608
};
2609+
queue = newQueue;
2610+
25942611
const stateHook: Hook = {
25952612
memoizedState: NoPendingHostTransition,
25962613
baseState: NoPendingHostTransition,
25972614
baseQueue: null,
2598-
queue: queue,
2615+
queue: newQueue,
25992616
next: null,
26002617
};
26012618

2602-
const dispatch: (Thenable<TransitionStatus> | TransitionStatus) => void =
2603-
(dispatchSetState.bind(null, formFiber, queue): any);
2604-
setPending = queue.dispatch = dispatch;
2605-
26062619
// Add the state hook to both fiber alternates. The idea is that the fiber
26072620
// had this hook all along.
26082621
formFiber.memoizedState = stateHook;
@@ -2613,15 +2626,14 @@ export function startHostTransition<F>(
26132626
} else {
26142627
// This fiber was already upgraded to be stateful.
26152628
const stateHook: Hook = formFiber.memoizedState;
2616-
const dispatch: (Thenable<TransitionStatus> | TransitionStatus) => void =
2617-
stateHook.queue.dispatch;
2618-
setPending = dispatch;
2629+
queue = stateHook.queue;
26192630
}
26202631

26212632
startTransition(
2633+
formFiber,
2634+
queue,
26222635
pendingState,
26232636
NoPendingHostTransition,
2624-
setPending,
26252637
// TODO: We can avoid this extra wrapper, somehow. Figure out layering
26262638
// once more of this function is implemented.
26272639
() => callback(formData),
@@ -2632,9 +2644,15 @@ function mountTransition(): [
26322644
boolean,
26332645
(callback: () => void, options?: StartTransitionOptions) => void,
26342646
] {
2635-
const [, setPending] = mountState((false: Thenable<boolean> | boolean));
2647+
const stateHook = mountStateImpl((false: Thenable<boolean> | boolean));
26362648
// The `start` method never changes.
2637-
const start = startTransition.bind(null, true, false, setPending);
2649+
const start = startTransition.bind(
2650+
null,
2651+
currentlyRenderingFiber,
2652+
stateHook.queue,
2653+
true,
2654+
false,
2655+
);
26382656
const hook = mountWorkInProgressHook();
26392657
hook.memoizedState = start;
26402658
return [false, start];

0 commit comments

Comments
 (0)