Warn when using useFormState (#28668)
## Overview useFormState has been replaced with useActionState. Warn when it's used. Also removes the `experimental_useFormState` warnings.
Ricky committed
Mar 29, 2024 at 13:40 UTC
18812b645c93a9c42f931fae57bbbab9c1f402b8
4 files changed
+39
-28
packages/react-dom/index.experimental.js
-28
@@ -25,31 +25,3 @@ export {
25
preinitModule,
26
version,
27
} from './src/client/ReactDOM';
28
-
29
-import type {Awaited} from 'shared/ReactTypes';
30
-import type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions';
31
-import {useFormStatus, useFormState} from './src/client/ReactDOM';
32
-
33
-export function experimental_useFormStatus(): FormStatus {
34
- if (__DEV__) {
35
- console.error(
36
- 'useFormStatus is now in canary. Remove the experimental_ prefix. ' +
37
- 'The prefixed alias will be removed in an upcoming release.',
38
- );
39
- }
40
- return useFormStatus();
41
-}
42
-
43
-export function experimental_useFormState<S, P>(
44
- action: (Awaited<S>, P) => S,
45
- initialState: Awaited<S>,
46
- permalink?: string,
47
-): [Awaited<S>, (P) => void, boolean] {
48
- if (__DEV__) {
49
- console.error(
50
- 'useFormState is now in canary. Remove the experimental_ prefix. ' +
51
- 'The prefixed alias will be removed in an upcoming release.',
52
- );
53
- }
54
- return useFormState(action, initialState, permalink);
55
-}
packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
+10
@@ -100,6 +100,16 @@ describe('ReactDOMFizzServer', () => {
100
}
101
PropTypes = require('prop-types');
102
if (__VARIANT__) {
103
+ const originalConsoleError = console.error;
104
+ console.error = (error, ...args) => {
105
+ if (
106
+ typeof error !== 'string' ||
107
+ error.indexOf('ReactDOM.useFormState has been deprecated') === -1
108
+ ) {
109
+ originalConsoleError(error, ...args);
110
+ }
111
+ };
112
+
113
// Remove after API is deleted.
114
useActionState = ReactDOM.useFormState;
115
} else {
packages/react-dom/src/__tests__/ReactDOMForm-test.js
+9
@@ -62,6 +62,15 @@ describe('ReactDOMForm', () => {
62
textCache = new Map();
63
64
if (__VARIANT__) {
65
+ const originalConsoleError = console.error;
66
+ console.error = (error, ...args) => {
67
+ if (
68
+ typeof error !== 'string' ||
69
+ error.indexOf('ReactDOM.useFormState has been deprecated') === -1
70
+ ) {
71
+ originalConsoleError(error, ...args);
72
+ }
73
+ };
74
// Remove after API is deleted.
75
useActionState = ReactDOM.useFormState;
76
} else {
packages/react-reconciler/src/ReactFiberHooks.js
+20
@@ -178,10 +178,12 @@ let didWarnAboutMismatchedHooksForComponent;
178
let didWarnUncachedGetSnapshot: void | true;
179
let didWarnAboutUseWrappedInTryCatch;
180
let didWarnAboutAsyncClientComponent;
181
+let didWarnAboutUseFormState;
182
if (__DEV__) {
183
didWarnAboutMismatchedHooksForComponent = new Set<string | null>();
184
didWarnAboutUseWrappedInTryCatch = new Set<string | null>();
185
didWarnAboutAsyncClientComponent = new Set<string | null>();
186
+ didWarnAboutUseFormState = new Set<string | null>();
187
}
188
189
export type Hook = {
@@ -386,6 +388,21 @@ function warnOnHookMismatchInDev(currentHookName: HookType): void {
388
}
389
}
390
391
+function warnOnUseFormStateInDev(): void {
392
+ if (__DEV__) {
393
+ const componentName = getComponentNameFromFiber(currentlyRenderingFiber);
394
+ if (!didWarnAboutUseFormState.has(componentName)) {
395
+ didWarnAboutUseFormState.add(componentName);
396
+
397
+ console.error(
398
+ 'ReactDOM.useFormState has been deprecated and replaced by ' +
399
+ 'React.useActionState. Please update %s to use React.useActionState.',
400
+ componentName,
401
+ );
402
+ }
403
+ }
404
+}
405
+
406
function warnIfAsyncClientComponent(Component: Function) {
407
if (__DEV__) {
408
// This dev-only check only works for detecting native async functions,
@@ -4000,6 +4017,7 @@ if (__DEV__) {
4017
): [Awaited<S>, (P) => void, boolean] {
4018
currentHookNameInDev = 'useFormState';
4019
updateHookTypesDev();
4020
+ warnOnUseFormStateInDev();
4021
return mountActionState(action, initialState, permalink);
4022
};
4023
(HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useActionState =
@@ -4182,6 +4200,7 @@ if (__DEV__) {
4200
): [Awaited<S>, (P) => void, boolean] {
4201
currentHookNameInDev = 'useFormState';
4202
updateHookTypesDev();
4203
+ warnOnUseFormStateInDev();
4204
return updateActionState(action, initialState, permalink);
4205
};
4206
(HooksDispatcherOnUpdateInDEV: Dispatcher).useActionState =
@@ -4364,6 +4383,7 @@ if (__DEV__) {
4383
): [Awaited<S>, (P) => void, boolean] {
4384
currentHookNameInDev = 'useFormState';
4385
updateHookTypesDev();
4386
+ warnOnUseFormStateInDev();
4387
return rerenderActionState(action, initialState, permalink);
4388
};
4389
(HooksDispatcherOnRerenderInDEV: Dispatcher).useActionState =