Skip to content

Commit ab1639d

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 d3e1720 commit ab1639d

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
@@ -1884,9 +1884,7 @@ function forceStoreRerender(fiber: Fiber) {
18841884
}
18851885
}
18861886

1887-
function mountState<S>(
1888-
initialState: (() => S) | S,
1889-
): [S, Dispatch<BasicStateAction<S>>] {
1887+
function mountStateImpl<S>(initialState: (() => S) | S): Hook {
18901888
const hook = mountWorkInProgressHook();
18911889
if (typeof initialState === 'function') {
18921890
// $FlowFixMe[incompatible-use]: Flow doesn't like mixed types
@@ -1901,9 +1899,20 @@ function mountState<S>(
19011899
lastRenderedState: (initialState: any),
19021900
};
19031901
hook.queue = queue;
1904-
const dispatch: Dispatch<BasicStateAction<S>> = (queue.dispatch =
1905-
(dispatchSetState.bind(null, currentlyRenderingFiber, queue): any));
1906-
return [hook.memoizedState, dispatch];
1902+
const dispatch: Dispatch<BasicStateAction<S>> = (dispatchSetState.bind(
1903+
null,
1904+
currentlyRenderingFiber,
1905+
queue,
1906+
): any);
1907+
queue.dispatch = dispatch;
1908+
return hook;
1909+
}
1910+
1911+
function mountState<S>(
1912+
initialState: (() => S) | S,
1913+
): [S, Dispatch<BasicStateAction<S>>] {
1914+
const hook = mountStateImpl(initialState);
1915+
return [hook.memoizedState, hook.queue.dispatch];
19071916
}
19081917

19091918
function updateState<S>(
@@ -2469,9 +2478,10 @@ function updateDeferredValueImpl<T>(hook: Hook, prevValue: T, value: T): T {
24692478
}
24702479

24712480
function startTransition<S>(
2481+
fiber: Fiber,
2482+
queue: UpdateQueue<S | Thenable<S>, BasicStateAction<S | Thenable<S>>>,
24722483
pendingState: S,
24732484
finishedState: S,
2474-
setPending: (Thenable<S> | S) => void,
24752485
callback: () => mixed,
24762486
options?: StartTransitionOptions,
24772487
): void {
@@ -2482,7 +2492,7 @@ function startTransition<S>(
24822492

24832493
const prevTransition = ReactCurrentBatchConfig.transition;
24842494
ReactCurrentBatchConfig.transition = null;
2485-
setPending(pendingState);
2495+
dispatchSetState(fiber, queue, pendingState);
24862496
const currentTransition = (ReactCurrentBatchConfig.transition =
24872497
({}: BatchConfigTransition));
24882498

@@ -2509,10 +2519,10 @@ function startTransition<S>(
25092519
returnValue,
25102520
finishedState,
25112521
);
2512-
setPending(maybeThenable);
2522+
dispatchSetState(fiber, queue, maybeThenable);
25132523
} else {
25142524
// Async actions are not enabled.
2515-
setPending(finishedState);
2525+
dispatchSetState(fiber, queue, finishedState);
25162526
callback();
25172527
}
25182528
} catch (error) {
@@ -2525,7 +2535,7 @@ function startTransition<S>(
25252535
status: 'rejected',
25262536
reason: error,
25272537
};
2528-
setPending(rejectedThenable);
2538+
dispatchSetState(fiber, queue, rejectedThenable);
25292539
} else {
25302540
// The error rethrowing behavior is only enabled when the async actions
25312541
// feature is on, even for sync actions.
@@ -2577,36 +2587,39 @@ export function startHostTransition<F>(
25772587
);
25782588
}
25792589

2580-
let setPending;
2590+
let queue: UpdateQueue<
2591+
Thenable<TransitionStatus> | TransitionStatus,
2592+
BasicStateAction<Thenable<TransitionStatus> | TransitionStatus>,
2593+
>;
25812594
if (formFiber.memoizedState === null) {
25822595
// Upgrade this host component fiber to be stateful. We're going to pretend
25832596
// it was stateful all along so we can reuse most of the implementation
25842597
// for function components and useTransition.
25852598
//
25862599
// Create the state hook used by TransitionAwareHostComponent. This is
25872600
// essentially an inlined version of mountState.
2588-
const queue: UpdateQueue<
2589-
Thenable<TransitionStatus> | TransitionStatus,
2601+
const newQueue: UpdateQueue<
25902602
Thenable<TransitionStatus> | TransitionStatus,
2603+
BasicStateAction<Thenable<TransitionStatus> | TransitionStatus>,
25912604
> = {
25922605
pending: null,
25932606
lanes: NoLanes,
2594-
dispatch: null,
2607+
// We're going to cheat and intentionally not create a bound dispatch
2608+
// method, because we can call it directly in startTransition.
2609+
dispatch: (null: any),
25952610
lastRenderedReducer: basicStateReducer,
25962611
lastRenderedState: NoPendingHostTransition,
25972612
};
2613+
queue = newQueue;
2614+
25982615
const stateHook: Hook = {
25992616
memoizedState: NoPendingHostTransition,
26002617
baseState: NoPendingHostTransition,
26012618
baseQueue: null,
2602-
queue: queue,
2619+
queue: newQueue,
26032620
next: null,
26042621
};
26052622

2606-
const dispatch: (Thenable<TransitionStatus> | TransitionStatus) => void =
2607-
(dispatchSetState.bind(null, formFiber, queue): any);
2608-
setPending = queue.dispatch = dispatch;
2609-
26102623
// Add the state hook to both fiber alternates. The idea is that the fiber
26112624
// had this hook all along.
26122625
formFiber.memoizedState = stateHook;
@@ -2617,15 +2630,14 @@ export function startHostTransition<F>(
26172630
} else {
26182631
// This fiber was already upgraded to be stateful.
26192632
const stateHook: Hook = formFiber.memoizedState;
2620-
const dispatch: (Thenable<TransitionStatus> | TransitionStatus) => void =
2621-
stateHook.queue.dispatch;
2622-
setPending = dispatch;
2633+
queue = stateHook.queue;
26232634
}
26242635

26252636
startTransition(
2637+
formFiber,
2638+
queue,
26262639
pendingState,
26272640
NoPendingHostTransition,
2628-
setPending,
26292641
// TODO: We can avoid this extra wrapper, somehow. Figure out layering
26302642
// once more of this function is implemented.
26312643
() => callback(formData),
@@ -2636,9 +2648,15 @@ function mountTransition(): [
26362648
boolean,
26372649
(callback: () => void, options?: StartTransitionOptions) => void,
26382650
] {
2639-
const [, setPending] = mountState((false: Thenable<boolean> | boolean));
2651+
const stateHook = mountStateImpl((false: Thenable<boolean> | boolean));
26402652
// The `start` method never changes.
2641-
const start = startTransition.bind(null, true, false, setPending);
2653+
const start = startTransition.bind(
2654+
null,
2655+
currentlyRenderingFiber,
2656+
stateHook.queue,
2657+
true,
2658+
false,
2659+
);
26422660
const hook = mountWorkInProgressHook();
26432661
hook.memoizedState = start;
26442662
return [false, start];

0 commit comments

Comments
 (0)