diff --git a/packages/react-dom/index.experimental.js b/packages/react-dom/index.experimental.js index 5090305e9d758..0d38031e60b21 100644 --- a/packages/react-dom/index.experimental.js +++ b/packages/react-dom/index.experimental.js @@ -25,31 +25,3 @@ export { preinitModule, version, } from './src/client/ReactDOM'; - -import type {Awaited} from 'shared/ReactTypes'; -import type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions'; -import {useFormStatus, useFormState} from './src/client/ReactDOM'; - -export function experimental_useFormStatus(): FormStatus { - if (__DEV__) { - console.error( - 'useFormStatus is now in canary. Remove the experimental_ prefix. ' + - 'The prefixed alias will be removed in an upcoming release.', - ); - } - return useFormStatus(); -} - -export function experimental_useFormState( - action: (Awaited, P) => S, - initialState: Awaited, - permalink?: string, -): [Awaited, (P) => void, boolean] { - if (__DEV__) { - console.error( - 'useFormState is now in canary. Remove the experimental_ prefix. ' + - 'The prefixed alias will be removed in an upcoming release.', - ); - } - return useFormState(action, initialState, permalink); -} diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js index a603ea5e731fb..1dcc42f5335a5 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js @@ -100,6 +100,16 @@ describe('ReactDOMFizzServer', () => { } PropTypes = require('prop-types'); if (__VARIANT__) { + const originalConsoleError = console.error; + console.error = (error, ...args) => { + if ( + typeof error !== 'string' || + error.indexOf('ReactDOM.useFormState has been deprecated') === -1 + ) { + originalConsoleError(error, ...args); + } + }; + // Remove after API is deleted. useActionState = ReactDOM.useFormState; } else { diff --git a/packages/react-dom/src/__tests__/ReactDOMForm-test.js b/packages/react-dom/src/__tests__/ReactDOMForm-test.js index 77eb4a3aebe41..2d7a34aa75cfd 100644 --- a/packages/react-dom/src/__tests__/ReactDOMForm-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMForm-test.js @@ -62,6 +62,15 @@ describe('ReactDOMForm', () => { textCache = new Map(); if (__VARIANT__) { + const originalConsoleError = console.error; + console.error = (error, ...args) => { + if ( + typeof error !== 'string' || + error.indexOf('ReactDOM.useFormState has been deprecated') === -1 + ) { + originalConsoleError(error, ...args); + } + }; // Remove after API is deleted. useActionState = ReactDOM.useFormState; } else { diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index b82ff9c383163..d4eff012844a7 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -178,10 +178,12 @@ let didWarnAboutMismatchedHooksForComponent; let didWarnUncachedGetSnapshot: void | true; let didWarnAboutUseWrappedInTryCatch; let didWarnAboutAsyncClientComponent; +let didWarnAboutUseFormState; if (__DEV__) { didWarnAboutMismatchedHooksForComponent = new Set(); didWarnAboutUseWrappedInTryCatch = new Set(); didWarnAboutAsyncClientComponent = new Set(); + didWarnAboutUseFormState = new Set(); } export type Hook = { @@ -386,6 +388,21 @@ function warnOnHookMismatchInDev(currentHookName: HookType): void { } } +function warnOnUseFormStateInDev(): void { + if (__DEV__) { + const componentName = getComponentNameFromFiber(currentlyRenderingFiber); + if (!didWarnAboutUseFormState.has(componentName)) { + didWarnAboutUseFormState.add(componentName); + + console.error( + 'ReactDOM.useFormState has been deprecated and replaced by ' + + 'React.useActionState. Please update %s to use React.useActionState.', + componentName, + ); + } + } +} + function warnIfAsyncClientComponent(Component: Function) { if (__DEV__) { // This dev-only check only works for detecting native async functions, @@ -4000,6 +4017,7 @@ if (__DEV__) { ): [Awaited, (P) => void, boolean] { currentHookNameInDev = 'useFormState'; updateHookTypesDev(); + warnOnUseFormStateInDev(); return mountActionState(action, initialState, permalink); }; (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useActionState = @@ -4182,6 +4200,7 @@ if (__DEV__) { ): [Awaited, (P) => void, boolean] { currentHookNameInDev = 'useFormState'; updateHookTypesDev(); + warnOnUseFormStateInDev(); return updateActionState(action, initialState, permalink); }; (HooksDispatcherOnUpdateInDEV: Dispatcher).useActionState = @@ -4364,6 +4383,7 @@ if (__DEV__) { ): [Awaited, (P) => void, boolean] { currentHookNameInDev = 'useFormState'; updateHookTypesDev(); + warnOnUseFormStateInDev(); return rerenderActionState(action, initialState, permalink); }; (HooksDispatcherOnRerenderInDEV: Dispatcher).useActionState =