[Devtools] Ensure initial read of `useFormStatus` returns `NotPendingTransition` (#28728)
Sebastian Silbermann committed
Aug 1, 2024 at 10:55 UTC
88ee14ffa57beb0689f26f0c52c357e3ac446af8
11 files changed
+72
-36
packages/react-art/src/ReactFiberConfigART.js
+12
@@ -16,6 +16,8 @@ import {
16
DefaultEventPriority,
17
NoEventPriority,
18
} from 'react-reconciler/src/ReactEventPriorities';
19
+import type {ReactContext} from 'shared/ReactTypes';
20
+import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
21
22
export {default as rendererVersion} from 'shared/ReactVersion';
23
export const rendererPackageName = 'react-art';
@@ -28,6 +30,8 @@ if (__DEV__) {
30
Object.freeze(NO_CONTEXT);
31
}
32
33
+export type TransitionStatus = mixed;
34
+
35
/** Helper Methods */
36
37
function addEventListeners(instance, type, listener) {
@@ -488,4 +492,12 @@ export function waitForCommitToBeReady() {
492
}
493
494
export const NotPendingTransition = null;
495
+export const HostTransitionContext: ReactContext<TransitionStatus> = {
496
+ $$typeof: REACT_CONTEXT_TYPE,
497
+ Provider: (null: any),
498
+ Consumer: (null: any),
499
+ _currentValue: NotPendingTransition,
500
+ _currentValue2: NotPendingTransition,
501
+ _threadCount: 0,
502
+};
503
export function resetFormInstance() {}
packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegrationDOM-test.js
+6
-1
@@ -119,7 +119,12 @@ describe('ReactHooksInspectionIntegration', () => {
119
isStateEditable: false,
120
name: 'FormStatus',
121
subHooks: [],
122
- value: null,
122
+ value: {
123
+ action: null,
124
+ data: null,
125
+ method: null,
126
+ pending: false,
127
+ },
128
},
129
{
130
debugInfo: null,
packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
+10
-1
@@ -14,7 +14,7 @@ import type {
14
IntersectionObserverOptions,
15
ObserveVisibleRectsCallback,
16
} from 'react-reconciler/src/ReactTestSelectors';
17
-import type {ReactScopeInstance} from 'shared/ReactTypes';
17
+import type {ReactContext, ReactScopeInstance} from 'shared/ReactTypes';
18
import type {AncestorInfoDev} from './validateDOMNesting';
19
import type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions';
20
import type {
@@ -32,6 +32,7 @@ import {getCurrentRootHostContainer} from 'react-reconciler/src/ReactFiberHostCo
32
33
import hasOwnProperty from 'shared/hasOwnProperty';
34
import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';
35
+import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
36
37
export {
38
setCurrentUpdatePriority,
@@ -3564,6 +3565,14 @@ function insertStylesheetIntoRoot(
3565
}
3566
3567
export const NotPendingTransition: TransitionStatus = NotPending;
3568
+export const HostTransitionContext: ReactContext<TransitionStatus> = {
3569
+ $$typeof: REACT_CONTEXT_TYPE,
3570
+ Provider: (null: any),
3571
+ Consumer: (null: any),
3572
+ _currentValue: NotPendingTransition,
3573
+ _currentValue2: NotPendingTransition,
3574
+ _threadCount: 0,
3575
+};
3576
3577
export type FormInstance = HTMLFormElement;
3578
export function resetFormInstance(form: FormInstance): void {
packages/react-native-renderer/src/ReactFiberConfigFabric.js
+10
@@ -60,6 +60,8 @@ import {
60
enableFabricCompleteRootInCommitPhase,
61
passChildrenWhenCloningPersistedNodes,
62
} from 'shared/ReactFeatureFlags';
63
+import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
64
+import type {ReactContext} from 'shared/ReactTypes';
65
66
export {default as rendererVersion} from 'shared/ReactVersion'; // TODO: Consider exporting the react-native version.
67
export const rendererPackageName = 'react-native-renderer';
@@ -544,6 +546,14 @@ export function waitForCommitToBeReady(): null {
546
}
547
548
export const NotPendingTransition: TransitionStatus = null;
549
+export const HostTransitionContext: ReactContext<TransitionStatus> = {
550
+ $$typeof: REACT_CONTEXT_TYPE,
551
+ Provider: (null: any),
552
+ Consumer: (null: any),
553
+ _currentValue: NotPendingTransition,
554
+ _currentValue2: NotPendingTransition,
555
+ _threadCount: 0,
556
+};
557
558
export type FormInstance = Instance;
559
export function resetFormInstance(form: Instance): void {}
packages/react-native-renderer/src/ReactFiberConfigNative.js
+11
@@ -32,6 +32,9 @@ import {
32
} from 'react-reconciler/src/ReactEventPriorities';
33
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
34
35
+import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
36
+import type {ReactContext} from 'shared/ReactTypes';
37
+
38
import {
39
getInspectorDataForViewTag,
40
getInspectorDataForViewAtPoint,
@@ -561,6 +564,14 @@ export function waitForCommitToBeReady(): null {
564
}
565
566
export const NotPendingTransition: TransitionStatus = null;
567
+export const HostTransitionContext: ReactContext<TransitionStatus> = {
568
+ $$typeof: REACT_CONTEXT_TYPE,
569
+ Provider: (null: any),
570
+ Consumer: (null: any),
571
+ _currentValue: NotPendingTransition,
572
+ _currentValue2: NotPendingTransition,
573
+ _threadCount: 0,
574
+};
575
576
export type FormInstance = Instance;
577
export function resetFormInstance(form: Instance): void {}
packages/react-reconciler/src/ReactFiberBeginWork.js
+1
-1
@@ -178,6 +178,7 @@ import {
178
isPrimaryRenderer,
179
getResource,
180
createHoistableInstance,
181
+ HostTransitionContext,
182
} from './ReactFiberConfig';
183
import type {SuspenseInstance} from './ReactFiberConfig';
184
import {shouldError, shouldSuspend} from './ReactFiberReconciler';
@@ -185,7 +186,6 @@ import {
186
pushHostContext,
187
pushHostContainer,
188
getRootHostContainer,
188
- HostTransitionContext,
189
} from './ReactFiberHostContext';
190
import {
191
suspenseStackCursor,
packages/react-reconciler/src/ReactFiberHooks.js
+2
-3
@@ -28,6 +28,7 @@ import type {Flags} from './ReactFiberFlags';
28
import type {TransitionStatus} from './ReactFiberConfig';
29
30
import {
31
+ HostTransitionContext,
32
NotPendingTransition as NoPendingHostTransition,
33
setCurrentUpdatePriority,
34
getCurrentUpdatePriority,
@@ -156,7 +157,6 @@ import {
157
peekEntangledActionThenable,
158
chainThenableValue,
159
} from './ReactFiberAsyncAction';
159
-import {HostTransitionContext} from './ReactFiberHostContext';
160
import {requestTransitionLane} from './ReactFiberRootScheduler';
161
import {isCurrentTreeHidden} from './ReactFiberHiddenContext';
162
import {requestCurrentTransition} from './ReactFiberTransition';
@@ -3276,8 +3276,7 @@ function useHostTransitionStatus(): TransitionStatus {
3276
if (!enableAsyncActions) {
3277
throw new Error('Not implemented.');
3278
}
3279
- const status: TransitionStatus | null = readContext(HostTransitionContext);
3280
- return status !== null ? status : NoPendingHostTransition;
3279
+ return readContext(HostTransitionContext);
3280
}
3281
3282
function mountId(): string {
packages/react-reconciler/src/ReactFiberHostContext.js
+6
-25
@@ -9,21 +9,17 @@
9
10
import type {Fiber} from './ReactInternalTypes';
11
import type {StackCursor} from './ReactFiberStack';
12
-import type {
13
- Container,
14
- HostContext,
15
- TransitionStatus,
16
-} from './ReactFiberConfig';
12
+import type {Container, HostContext} from './ReactFiberConfig';
13
import type {Hook} from './ReactFiberHooks';
18
-import type {ReactContext} from 'shared/ReactTypes';
14
15
import {
16
getChildHostContext,
17
getRootHostContext,
18
+ HostTransitionContext,
19
+ NotPendingTransition,
20
isPrimaryRenderer,
21
} from './ReactFiberConfig';
22
import {createCursor, push, pop} from './ReactFiberStack';
26
-import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
23
import {enableAsyncActions} from 'shared/ReactFeatureFlags';
24
25
const contextStackCursor: StackCursor<HostContext | null> = createCursor(null);
@@ -38,21 +34,6 @@ const rootInstanceStackCursor: StackCursor<Container | null> =
34
const hostTransitionProviderCursor: StackCursor<Fiber | null> =
35
createCursor(null);
36
41
-// TODO: This should initialize to NotPendingTransition, a constant
42
-// imported from the fiber config. However, because of a cycle in the module
43
-// graph, that value isn't defined during this module's initialization. I can't
44
-// think of a way to work around this without moving that value out of the
45
-// fiber config. For now, the "no provider" case is handled when reading,
46
-// inside useHostTransitionStatus.
47
-export const HostTransitionContext: ReactContext<TransitionStatus | null> = {
48
- $$typeof: REACT_CONTEXT_TYPE,
49
- Provider: (null: any),
50
- Consumer: (null: any),
51
- _currentValue: null,
52
- _currentValue2: null,
53
- _threadCount: 0,
54
-};
55
-
37
function requiredContext<Value>(c: Value | null): Value {
38
if (__DEV__) {
39
if (c === null) {
@@ -150,13 +131,13 @@ function popHostContext(fiber: Fiber): void {
131
pop(hostTransitionProviderCursor, fiber);
132
133
// When popping the transition provider, we reset the context value back
153
- // to `null`. We can do this because you're not allowd to nest forms. If
134
+ // to `NotPendingTransition`. We can do this because you're not allowed to nest forms. If
135
// we allowed for multiple nested host transition providers, then we'd
136
// need to reset this to the parent provider's status.
137
if (isPrimaryRenderer) {
157
- HostTransitionContext._currentValue = null;
138
+ HostTransitionContext._currentValue = NotPendingTransition;
139
} else {
159
- HostTransitionContext._currentValue2 = null;
140
+ HostTransitionContext._currentValue2 = NotPendingTransition;
141
}
142
}
143
}
packages/react-reconciler/src/ReactFiberNewContext.js
+2
-5
@@ -20,7 +20,7 @@ import type {SharedQueue} from './ReactFiberClassUpdateQueue';
20
import type {TransitionStatus} from './ReactFiberConfig';
21
import type {Hook} from './ReactFiberHooks';
22
23
-import {isPrimaryRenderer} from './ReactFiberConfig';
23
+import {isPrimaryRenderer, HostTransitionContext} from './ReactFiberConfig';
24
import {createCursor, push, pop} from './ReactFiberStack';
25
import {
26
ContextProvider,
@@ -48,10 +48,7 @@ import {
48
enableAsyncActions,
49
enableRenderableContext,
50
} from 'shared/ReactFeatureFlags';
51
-import {
52
- getHostTransitionProvider,
53
- HostTransitionContext,
54
-} from './ReactFiberHostContext';
51
+import {getHostTransitionProvider} from './ReactFiberHostContext';
52
import isArray from '../../shared/isArray';
53
import {enableContextProfiling} from '../../shared/ReactFeatureFlags';
54
packages/react-reconciler/src/forks/ReactFiberConfig.custom.js
+1
@@ -83,6 +83,7 @@ export const startSuspendingCommit = $$$config.startSuspendingCommit;
83
export const suspendInstance = $$$config.suspendInstance;
84
export const waitForCommitToBeReady = $$$config.waitForCommitToBeReady;
85
export const NotPendingTransition = $$$config.NotPendingTransition;
86
+export const HostTransitionContext = $$$config.HostTransitionContext;
87
export const resetFormInstance = $$$config.resetFormInstance;
88
export const bindToConsole = $$$config.bindToConsole;
89
packages/react-test-renderer/src/ReactFiberConfigTestHost.js
+11
@@ -7,7 +7,10 @@
7
* @flow
8
*/
9
10
+import type {ReactContext} from 'shared/ReactTypes';
11
+
12
import isArray from 'shared/isArray';
13
+import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
14
import {
15
DefaultEventPriority,
16
NoEventPriority,
@@ -352,6 +355,14 @@ export function waitForCommitToBeReady(): null {
355
}
356
357
export const NotPendingTransition: TransitionStatus = null;
358
+export const HostTransitionContext: ReactContext<TransitionStatus> = {
359
+ $$typeof: REACT_CONTEXT_TYPE,
360
+ Provider: (null: any),
361
+ Consumer: (null: any),
362
+ _currentValue: NotPendingTransition,
363
+ _currentValue2: NotPendingTransition,
364
+ _threadCount: 0,
365
+};
366
367
export type FormInstance = Instance;
368
export function resetFormInstance(form: Instance): void {}