Skip to content

Commit 6362d4c

Browse files
committed
add transition name to startTransition
Add a transitionName to start transition, store the transition start time and name in the batch config, and pass it to the root on render
1 parent f86c96f commit 6362d4c

File tree

12 files changed

+269
-13
lines changed

12 files changed

+269
-13
lines changed

packages/react-debug-tools/src/ReactDebugHooks.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
MutableSourceSubscribeFn,
1414
ReactContext,
1515
ReactProviderType,
16+
StartTransitionOptions,
1617
} from 'shared/ReactTypes';
1718
import type {
1819
Fiber,
@@ -290,7 +291,10 @@ function useSyncExternalStore<T>(
290291
return value;
291292
}
292293

293-
function useTransition(): [boolean, (() => void) => void] {
294+
function useTransition(): [
295+
boolean,
296+
(callback: () => void, options?: StartTransitionOptions) => void,
297+
] {
294298
// useTransition() composes multiple hooks internally.
295299
// Advance the current hook index the same number of times
296300
// so that subsequent hooks have the right memoized state.

packages/react-dom/src/events/ReactDOMEventListener.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import type {AnyNativeEvent} from '../events/PluginModuleType';
1111
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
1212
import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig';
1313
import type {DOMEventName} from '../events/DOMEventNames';
14-
import {enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay} from 'shared/ReactFeatureFlags';
14+
import {
15+
enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
16+
enableTransitionTracing,
17+
} from 'shared/ReactFeatureFlags';
1518
import {
1619
isDiscreteEventThatRequiresHydration,
1720
queueDiscreteEvent,
@@ -118,12 +121,23 @@ function dispatchDiscreteEvent(
118121
const previousPriority = getCurrentUpdatePriority();
119122
const prevTransition = ReactCurrentBatchConfig.transition;
120123
ReactCurrentBatchConfig.transition = 0;
124+
125+
let prevTransitionInfo = null;
126+
if (enableTransitionTracing) {
127+
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
128+
ReactCurrentBatchConfig.transitionInfo = null;
129+
}
130+
121131
try {
122132
setCurrentUpdatePriority(DiscreteEventPriority);
123133
dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);
124134
} finally {
125135
setCurrentUpdatePriority(previousPriority);
126136
ReactCurrentBatchConfig.transition = prevTransition;
137+
138+
if (enableTransitionTracing) {
139+
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
140+
}
127141
}
128142
}
129143

@@ -136,12 +150,23 @@ function dispatchContinuousEvent(
136150
const previousPriority = getCurrentUpdatePriority();
137151
const prevTransition = ReactCurrentBatchConfig.transition;
138152
ReactCurrentBatchConfig.transition = 0;
153+
154+
let prevTransitionInfo = null;
155+
if (enableTransitionTracing) {
156+
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
157+
ReactCurrentBatchConfig.transitionInfo = null;
158+
}
159+
139160
try {
140161
setCurrentUpdatePriority(ContinuousEventPriority);
141162
dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);
142163
} finally {
143164
setCurrentUpdatePriority(previousPriority);
144165
ReactCurrentBatchConfig.transition = prevTransition;
166+
167+
if (enableTransitionTracing) {
168+
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
169+
}
145170
}
146171
}
147172

packages/react-reconciler/src/ReactFiberHooks.new.js

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
MutableSourceGetSnapshotFn,
1313
MutableSourceSubscribeFn,
1414
ReactContext,
15+
StartTransitionOptions,
1516
} from 'shared/ReactTypes';
1617
import type {Fiber, Dispatcher, HookType} from './ReactInternalTypes';
1718
import type {Lanes, Lane} from './ReactFiberLane.new';
@@ -31,6 +32,7 @@ import {
3132
enableLazyContextPropagation,
3233
enableSuspenseLayoutEffectSemantics,
3334
enableUseMutableSource,
35+
enableTransitionTracing,
3436
} from 'shared/ReactFeatureFlags';
3537

3638
import {
@@ -111,6 +113,7 @@ import {
111113
import {pushInterleavedQueue} from './ReactFiberInterleavedUpdates.new';
112114
import {warnOnSubscriptionInsideStartTransition} from 'shared/ReactFeatureFlags';
113115
import {getTreeId} from './ReactFiberTreeContext.new';
116+
import {getCurrentEventStartTime} from './ReactFiberHostConfig';
114117

115118
const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;
116119

@@ -1929,10 +1932,21 @@ function mountDeferredValue<T>(value: T): T {
19291932
mountEffect(() => {
19301933
const prevTransition = ReactCurrentBatchConfig.transition;
19311934
ReactCurrentBatchConfig.transition = 1;
1935+
1936+
let prevTransitionInfo = null;
1937+
if (enableTransitionTracing) {
1938+
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
1939+
ReactCurrentBatchConfig.transitionInfo = null;
1940+
}
1941+
19321942
try {
19331943
setValue(value);
19341944
} finally {
19351945
ReactCurrentBatchConfig.transition = prevTransition;
1946+
1947+
if (enableTransitionTracing) {
1948+
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
1949+
}
19361950
}
19371951
}, [value]);
19381952
return prevValue;
@@ -1943,10 +1957,21 @@ function updateDeferredValue<T>(value: T): T {
19431957
updateEffect(() => {
19441958
const prevTransition = ReactCurrentBatchConfig.transition;
19451959
ReactCurrentBatchConfig.transition = 1;
1960+
1961+
let prevTransitionInfo = null;
1962+
if (enableTransitionTracing) {
1963+
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
1964+
ReactCurrentBatchConfig.transitionInfo = null;
1965+
}
1966+
19461967
try {
19471968
setValue(value);
19481969
} finally {
19491970
ReactCurrentBatchConfig.transition = prevTransition;
1971+
1972+
if (enableTransitionTracing) {
1973+
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
1974+
}
19501975
}
19511976
}, [value]);
19521977
return prevValue;
@@ -1957,16 +1982,27 @@ function rerenderDeferredValue<T>(value: T): T {
19571982
updateEffect(() => {
19581983
const prevTransition = ReactCurrentBatchConfig.transition;
19591984
ReactCurrentBatchConfig.transition = 1;
1985+
1986+
let prevTransitionInfo = null;
1987+
if (enableTransitionTracing) {
1988+
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
1989+
ReactCurrentBatchConfig.transitionInfo = null;
1990+
}
1991+
19601992
try {
19611993
setValue(value);
19621994
} finally {
19631995
ReactCurrentBatchConfig.transition = prevTransition;
1996+
1997+
if (enableTransitionTracing) {
1998+
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
1999+
}
19642000
}
19652001
}, [value]);
19662002
return prevValue;
19672003
}
19682004

1969-
function startTransition(setPending, callback) {
2005+
function startTransition(setPending, callback, options) {
19702006
const previousPriority = getCurrentUpdatePriority();
19712007
setCurrentUpdatePriority(
19722008
higherEventPriority(previousPriority, ContinuousEventPriority),
@@ -1976,12 +2012,29 @@ function startTransition(setPending, callback) {
19762012

19772013
const prevTransition = ReactCurrentBatchConfig.transition;
19782014
ReactCurrentBatchConfig.transition = 1;
2015+
2016+
let prevTransitionInfo = null;
2017+
if (enableTransitionTracing) {
2018+
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
2019+
if (options !== undefined && options.name !== undefined) {
2020+
ReactCurrentBatchConfig.transitionInfo = {
2021+
name: options.name,
2022+
startTime: getCurrentEventStartTime(),
2023+
};
2024+
}
2025+
}
2026+
19792027
try {
19802028
setPending(false);
19812029
callback();
19822030
} finally {
19832031
setCurrentUpdatePriority(previousPriority);
19842032
ReactCurrentBatchConfig.transition = prevTransition;
2033+
2034+
if (enableTransitionTracing) {
2035+
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
2036+
}
2037+
19852038
if (__DEV__) {
19862039
if (
19872040
prevTransition !== 1 &&
@@ -2002,7 +2055,10 @@ function startTransition(setPending, callback) {
20022055
}
20032056
}
20042057

2005-
function mountTransition(): [boolean, (() => void) => void] {
2058+
function mountTransition(): [
2059+
boolean,
2060+
(callback: () => void, options?: StartTransitionOptions) => void,
2061+
] {
20062062
const [isPending, setPending] = mountState(false);
20072063
// The `start` method never changes.
20082064
const start = startTransition.bind(null, setPending);
@@ -2011,14 +2067,20 @@ function mountTransition(): [boolean, (() => void) => void] {
20112067
return [isPending, start];
20122068
}
20132069

2014-
function updateTransition(): [boolean, (() => void) => void] {
2070+
function updateTransition(): [
2071+
boolean,
2072+
(callback: () => void, options?: StartTransitionOptions) => void,
2073+
] {
20152074
const [isPending] = updateState(false);
20162075
const hook = updateWorkInProgressHook();
20172076
const start = hook.memoizedState;
20182077
return [isPending, start];
20192078
}
20202079

2021-
function rerenderTransition(): [boolean, (() => void) => void] {
2080+
function rerenderTransition(): [
2081+
boolean,
2082+
(callback: () => void, options?: StartTransitionOptions) => void,
2083+
] {
20222084
const [isPending] = rerenderState(false);
20232085
const hook = updateWorkInProgressHook();
20242086
const start = hook.memoizedState;

packages/react-reconciler/src/ReactFiberLane.new.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @flow
88
*/
99

10-
import type {FiberRoot} from './ReactInternalTypes';
10+
import type {FiberRoot, Transition} from './ReactInternalTypes';
1111

1212
// TODO: Ideally these types would be opaque but that doesn't work well with
1313
// our reconciler fork infra, since these leak into non-reconciler packages.
@@ -20,6 +20,7 @@ import {
2020
enableSchedulingProfiler,
2121
enableUpdaterTracking,
2222
allowConcurrentByDefault,
23+
enableTransitionTracing,
2324
} from 'shared/ReactFeatureFlags';
2425
import {isDevToolsPresent} from './ReactFiberDevToolsHook.new';
2526
import {ConcurrentUpdatesByDefaultMode, NoMode} from './ReactTypeOfMode';
@@ -792,3 +793,16 @@ export function movePendingFibersToMemoized(root: FiberRoot, lanes: Lanes) {
792793
lanes &= ~lane;
793794
}
794795
}
796+
797+
export function addTransitionToLanesMap(
798+
root: FiberRoot,
799+
transition: Transition,
800+
lane: Lane,
801+
) {
802+
if (enableTransitionTracing) {
803+
const transitionLanesMap = root.transitionLanes;
804+
const index = laneToIndex(lane);
805+
const transitions = transitionLanesMap[index];
806+
transitions.add(transition);
807+
}
808+
}

packages/react-reconciler/src/ReactFiberRoot.new.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) {
7878

7979
if (enableTransitionTracing) {
8080
this.transitionCallbacks = null;
81+
const transitionLanesMap = (this.transitionLanes = []);
82+
for (let i = 0; i < TotalLanes; i++) {
83+
transitionLanesMap.push(new Set());
84+
}
8185
}
8286

8387
if (enableProfilerTimer && enableProfilerCommitHooks) {

0 commit comments

Comments
 (0)