Skip to content

Commit 415c80a

Browse files
committed
Entangle nested startTransition types
startTransition(() => { startTransition(() => { addTransitionType(...) }); setState(...); }); When the inner one finishes you could drop its transition types because it has no work scheduled on it.
1 parent 5227402 commit 415c80a

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

packages/react-reconciler/src/ReactFiberHooks.js

+54-2
Original file line numberDiff line numberDiff line change
@@ -2161,7 +2161,15 @@ function runActionStateAction<S, P>(
21612161
const prevTransition = ReactSharedInternals.T;
21622162
const currentTransition: Transition = ({}: any);
21632163
if (enableViewTransition) {
2164-
currentTransition.types = null;
2164+
currentTransition.types =
2165+
prevTransition !== null
2166+
? // If we're a nested transition, we should use the same set as the parent
2167+
// since we're conceptually always joined into the same entangled transition.
2168+
// In practice, this only matters if we add transition types in the inner
2169+
// without setting state. In that case, the inner transition can finish
2170+
// without waiting for the outer.
2171+
prevTransition.types
2172+
: null;
21652173
}
21662174
if (enableGestureTransition) {
21672175
currentTransition.gesture = null;
@@ -2184,6 +2192,24 @@ function runActionStateAction<S, P>(
21842192
} catch (error) {
21852193
onActionError(actionQueue, node, error);
21862194
} finally {
2195+
if (prevTransition !== null && currentTransition.types !== null) {
2196+
// If we created a new types set in the inner transition, we transfer it to the parent
2197+
// since they should share the same set. They're conceptually entangled.
2198+
if (__DEV__) {
2199+
if (
2200+
prevTransition.types !== null &&
2201+
prevTransition.types !== currentTransition.types
2202+
) {
2203+
// Just assert that assumption holds that we're not overriding anything.
2204+
console.error(
2205+
'We expected inner Transitions to have transferred the outer types set and ' +
2206+
'that you cannot add to the outer Transition while inside the inner.' +
2207+
'This is a bug in React.',
2208+
);
2209+
}
2210+
}
2211+
prevTransition.types = currentTransition.types;
2212+
}
21872213
ReactSharedInternals.T = prevTransition;
21882214

21892215
if (__DEV__) {
@@ -3057,7 +3083,15 @@ function startTransition<S>(
30573083
const prevTransition = ReactSharedInternals.T;
30583084
const currentTransition: Transition = ({}: any);
30593085
if (enableViewTransition) {
3060-
currentTransition.types = null;
3086+
currentTransition.types =
3087+
prevTransition !== null
3088+
? // If we're a nested transition, we should use the same set as the parent
3089+
// since we're conceptually always joined into the same entangled transition.
3090+
// In practice, this only matters if we add transition types in the inner
3091+
// without setting state. In that case, the inner transition can finish
3092+
// without waiting for the outer.
3093+
prevTransition.types
3094+
: null;
30613095
}
30623096
if (enableGestureTransition) {
30633097
currentTransition.gesture = null;
@@ -3144,6 +3178,24 @@ function startTransition<S>(
31443178
} finally {
31453179
setCurrentUpdatePriority(previousPriority);
31463180

3181+
if (prevTransition !== null && currentTransition.types !== null) {
3182+
// If we created a new types set in the inner transition, we transfer it to the parent
3183+
// since they should share the same set. They're conceptually entangled.
3184+
if (__DEV__) {
3185+
if (
3186+
prevTransition.types !== null &&
3187+
prevTransition.types !== currentTransition.types
3188+
) {
3189+
// Just assert that assumption holds that we're not overriding anything.
3190+
console.error(
3191+
'We expected inner Transitions to have transferred the outer types set and ' +
3192+
'that you cannot add to the outer Transition while inside the inner.' +
3193+
'This is a bug in React.',
3194+
);
3195+
}
3196+
}
3197+
prevTransition.types = currentTransition.types;
3198+
}
31473199
ReactSharedInternals.T = prevTransition;
31483200

31493201
if (__DEV__) {

packages/react/src/ReactStartTransition.js

+27-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,15 @@ export function startTransition(
4747
const prevTransition = ReactSharedInternals.T;
4848
const currentTransition: Transition = ({}: any);
4949
if (enableViewTransition) {
50-
currentTransition.types = null;
50+
currentTransition.types =
51+
prevTransition !== null
52+
? // If we're a nested transition, we should use the same set as the parent
53+
// since we're conceptually always joined into the same entangled transition.
54+
// In practice, this only matters if we add transition types in the inner
55+
// without setting state. In that case, the inner transition can finish
56+
// without waiting for the outer.
57+
prevTransition.types
58+
: null;
5159
}
5260
if (enableGestureTransition) {
5361
currentTransition.gesture = null;
@@ -84,6 +92,24 @@ export function startTransition(
8492
reportGlobalError(error);
8593
} finally {
8694
warnAboutTransitionSubscriptions(prevTransition, currentTransition);
95+
if (prevTransition !== null && currentTransition.types !== null) {
96+
// If we created a new types set in the inner transition, we transfer it to the parent
97+
// since they should share the same set. They're conceptually entangled.
98+
if (__DEV__) {
99+
if (
100+
prevTransition.types !== null &&
101+
prevTransition.types !== currentTransition.types
102+
) {
103+
// Just assert that assumption holds that we're not overriding anything.
104+
console.error(
105+
'We expected inner Transitions to have transferred the outer types set and ' +
106+
'that you cannot add to the outer Transition while inside the inner.' +
107+
'This is a bug in React.',
108+
);
109+
}
110+
}
111+
prevTransition.types = currentTransition.types;
112+
}
87113
ReactSharedInternals.T = prevTransition;
88114
}
89115
}

0 commit comments

Comments
 (0)