@samitouri / QOS-React / commits / 374b5d26c2

Scaffolding for requestFormReset API (#28808)

Based on: - #28804 --- This sets adds a new ReactDOM export called requestFormReset, including setting up the export and creating a method on the internal ReactDOM dispatcher. It does not yet add any implementation. Doing this in its own commit for review purposes. The API itself will be explained in the next PR.

Andrew Clark committed Apr 10, 2024 at 16:55 UTC 374b5d26c2a379fe87ee6817217c8956c4e39aac
16 files changed +53 -3
packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
+19
@@ -102,6 +102,7 @@ import {listenToAllSupportedEvents} from '../events/DOMPluginEventSystem';
102 import {validateLinkPropsForStyleResource} from '../shared/ReactDOMResourceValidation';
103 import escapeSelectorAttributeValueInsideDoubleQuotes from './escapeSelectorAttributeValueInsideDoubleQuotes';
104 import {flushSyncWork as flushSyncWorkOnAllRoots} from 'react-reconciler/src/ReactFiberWorkLoop';
105 +import {requestFormReset as requestFormResetOnFiber} from 'react-reconciler/src/ReactFiberHooks';
106
107 import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';
108
@@ -1928,6 +1929,7 @@ ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = {
1929 f /* flushSyncWork */: disableLegacyMode
1930 ? flushSyncWork
1931 : previousDispatcher.f /* flushSyncWork */,
1932 + r: requestFormReset,
1933 D /* prefetchDNS */: prefetchDNS,
1934 C /* preconnect */: preconnect,
1935 L /* preload */: preload,
@@ -1951,6 +1953,23 @@ function flushSyncWork() {
1953 }
1954 }
1955
1956 +function requestFormReset(form: HTMLFormElement) {
1957 + const formInst = getInstanceFromNodeDOMTree(form);
1958 + if (
1959 + formInst !== null &&
1960 + formInst.tag === HostComponent &&
1961 + formInst.type === 'form'
1962 + ) {
1963 + requestFormResetOnFiber(formInst);
1964 + } else {
1965 + // This form was either not rendered by this React renderer (or it's an
1966 + // invalid type). Try the next one.
1967 + //
1968 + // The last implementation in the sequence will throw an error.
1969 + previousDispatcher.r(/* requestFormReset */ form);
1970 + }
1971 +}
1972 +
1973 // We expect this to get inlined. It is a function mostly to communicate the special nature of
1974 // how we resolve the HoistableRoot for ReactDOM.pre*() methods. Because we support calling
1975 // these methods outside of render there is no way to know which Document or ShadowRoot is 'scoped'
packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js
+1
@@ -28,6 +28,7 @@ const previousDispatcher =
28 ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */
29 ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = {
30 f /* flushSyncWork */: previousDispatcher.f /* flushSyncWork */,
31 + r /* requestFormReset */: previousDispatcher.r /* requestFormReset */,
32 D /* prefetchDNS */: prefetchDNS,
33 C /* preconnect */: preconnect,
34 L /* preload */: preload,
packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
+1
@@ -88,6 +88,7 @@ const previousDispatcher =
88 ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */
89 ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = {
90 f /* flushSyncWork */: previousDispatcher.f /* flushSyncWork */,
91 + r /* requestFormReset */: previousDispatcher.r /* requestFormReset */,
92 D /* prefetchDNS */: prefetchDNS,
93 C /* preconnect */: preconnect,
94 L /* preload */: preload,
packages/react-dom-bindings/src/shared/ReactDOMFormActions.js
+6
@@ -12,6 +12,7 @@ import type {Awaited} from 'shared/ReactTypes';
12
13 import {enableAsyncActions} from 'shared/ReactFeatureFlags';
14 import ReactSharedInternals from 'shared/ReactSharedInternals';
15 +import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';
16
17 type FormStatusNotPending = {|
18 pending: false,
@@ -87,3 +88,8 @@ export function useFormState<S, P>(
88 return dispatcher.useFormState(action, initialState, permalink);
89 }
90 }
91 +
92 +export function requestFormReset(form: HTMLFormElement) {
93 + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */
94 + .r(/* requestFormReset */ form);
95 +}
packages/react-dom/index.classic.fb.js
+1
@@ -25,6 +25,7 @@ export {
25 unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
26 useFormStatus,
27 useFormState,
28 + requestFormReset,
29 prefetchDNS,
30 preconnect,
31 preload,
packages/react-dom/index.experimental.js
+1
@@ -17,6 +17,7 @@ export {
17 unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
18 useFormStatus,
19 useFormState,
20 + requestFormReset,
21 prefetchDNS,
22 preconnect,
23 preload,
packages/react-dom/index.js
+1
@@ -20,6 +20,7 @@ export {
20 unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
21 useFormStatus,
22 useFormState,
23 + requestFormReset,
24 prefetchDNS,
25 preconnect,
26 preload,
packages/react-dom/index.modern.fb.js
+1
@@ -16,6 +16,7 @@ export {
16 unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
17 useFormStatus,
18 useFormState,
19 + requestFormReset,
20 prefetchDNS,
21 preconnect,
22 preload,
packages/react-dom/index.stable.js
+1
@@ -16,6 +16,7 @@ export {
16 unstable_batchedUpdates,
17 useFormStatus,
18 useFormState,
19 + requestFormReset,
20 prefetchDNS,
21 preconnect,
22 preload,
packages/react-dom/src/ReactDOMSharedInternals.js
+8
@@ -29,8 +29,16 @@ export type ReactDOMInternalsDev = ReactDOMInternals & {
29
30 function noop() {}
31
32 +function requestFormReset(element: HTMLFormElement) {
33 + throw new Error(
34 + 'Invalid form element. requestFormReset must be passed a form that was ' +
35 + 'rendered by React.',
36 + );
37 +}
38 +
39 const DefaultDispatcher: HostDispatcher = {
40 f /* flushSyncWork */: noop,
41 + r /* requestFormReset */: requestFormReset,
42 D /* prefetchDNS */: noop,
43 C /* preconnect */: noop,
44 L /* preload */: noop,
packages/react-dom/src/ReactDOMSharedInternalsFB.js
+1
@@ -27,6 +27,7 @@ function noop() {}
27
28 const DefaultDispatcher: HostDispatcher = {
29 f /* flushSyncWork */: noop,
30 + r /* requestFormReset */: noop,
31 D /* prefetchDNS */: noop,
32 C /* preconnect */: noop,
33 L /* preload */: noop,
packages/react-dom/src/client/ReactDOM.js
+1
@@ -48,6 +48,7 @@ export {
48 export {
49 useFormStatus,
50 useFormState,
51 + requestFormReset,
52 } from 'react-dom-bindings/src/shared/ReactDOMFormActions';
53
54 if (__DEV__) {
packages/react-dom/src/client/ReactDOMFB.js
+1
@@ -48,6 +48,7 @@ export {
48 export {
49 useFormStatus,
50 useFormState,
51 + requestFormReset,
52 } from 'react-dom-bindings/src/shared/ReactDOMFormActions';
53
54 if (__DEV__) {
packages/react-dom/src/shared/ReactDOMTypes.js
+1
@@ -83,6 +83,7 @@ export type PreinitModuleScriptOptions = {
83
84 export type HostDispatcher = {
85 f /* flushSyncWork */: () => boolean | void,
86 + r /* requestFormReset */: (form: HTMLFormElement) => void,
87 D /* prefetchDNS */: (href: string) => void,
88 C /* preconnect */: (href: string, crossOrigin?: ?CrossOriginEnum) => void,
89 L /* preload */: (
packages/react-reconciler/src/ReactFiberHooks.js
+7 -2
@@ -3008,13 +3008,18 @@ export function startHostTransition<F>(
3008 // once more of this function is implemented.
3009 () => {
3010 // Automatically reset the form when the action completes.
3011 - requestFormReset(formFiber);
3011 + requestFormResetImpl(formFiber);
3012 return callback(formData);
3013 },
3014 );
3015 }
3016
3017 -function requestFormReset(formFiber: Fiber) {
3017 +export function requestFormReset(formFiber: Fiber) {
3018 + // TODO: Not yet implemented. Need to upgrade the fiber to be stateful
3019 + // before scheduling the form reset.
3020 +}
3021 +
3022 +function requestFormResetImpl(formFiber: Fiber) {
3023 const transition = requestCurrentTransition();
3024
3025 if (__DEV__) {
scripts/error-codes/codes.json
+2 -1
@@ -506,5 +506,6 @@
506 "518": "Saw multiple hydration diff roots in a pass. This is a bug in React.",
507 "519": "Hydration Mismatch Exception: This is not a real error, and should not leak into userspace. If you're seeing this, it's likely a bug in React.",
508 "520": "There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.",
509 - "521": "flushSyncWork should not be called from builds that support legacy mode. This is a bug in React."
509 + "521": "flushSyncWork should not be called from builds that support legacy mode. This is a bug in React.",
510 + "522": "Invalid form element. requestFormReset must be passed a form that was rendered by React."
511 }