diff --git a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js index d07ab9e71b0b3..f89e95bcf5dde 100644 --- a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js +++ b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js @@ -14,7 +14,6 @@ let act; let React; let ReactDOM; let ReactDOMClient; -let PropTypes; let findDOMNode; const clone = function (o) { @@ -99,7 +98,6 @@ describe('ReactComponentLifeCycle', () => { findDOMNode = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; ReactDOMClient = require('react-dom/client'); - PropTypes = require('prop-types'); }); it('should not reuse an instance when it has been unmounted', async () => { @@ -1114,72 +1112,6 @@ describe('ReactComponentLifeCycle', () => { }); }); - if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) { - // @gate !disableLegacyContext - it('calls effects on module-pattern component', async () => { - const log = []; - - function Parent() { - return { - render() { - expect(typeof this.props).toBe('object'); - log.push('render'); - return ; - }, - UNSAFE_componentWillMount() { - log.push('will mount'); - }, - componentDidMount() { - log.push('did mount'); - }, - componentDidUpdate() { - log.push('did update'); - }, - getChildContext() { - return {x: 2}; - }, - }; - } - Parent.childContextTypes = { - x: PropTypes.number, - }; - function Child(props, context) { - expect(context.x).toBe(2); - return
; - } - Child.contextTypes = { - x: PropTypes.number, - }; - - const root = ReactDOMClient.createRoot(document.createElement('div')); - await expect(async () => { - await act(() => { - root.render( c && log.push('ref')} />); - }); - }).toErrorDev( - 'Warning: The component appears to be a function component that returns a class instance. ' + - 'Change Parent to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`Parent.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", - ); - await act(() => { - root.render( c && log.push('ref')} />); - }); - - expect(log).toEqual([ - 'will mount', - 'render', - 'did mount', - 'ref', - - 'render', - 'did update', - 'ref', - ]); - }); - } - it('should warn if getDerivedStateFromProps returns undefined', async () => { class MyComponent extends React.Component { state = {}; diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js index 561928b24faf3..5959cdefccfe3 100644 --- a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js @@ -211,64 +211,35 @@ describe('ReactCompositeComponent', () => { }); }); - if (require('shared/ReactFeatureFlags').disableModulePatternComponents) { - it('should not support module pattern components', async () => { - function Child({test}) { - return { - render() { - return
{test}
; - }, - }; - } + it('should not support module pattern components', async () => { + function Child({test}) { + return { + render() { + return
{test}
; + }, + }; + } - const el = document.createElement('div'); - const root = ReactDOMClient.createRoot(el); + const el = document.createElement('div'); + const root = ReactDOMClient.createRoot(el); + await expect(async () => { await expect(async () => { - await expect(async () => { - await act(() => { - root.render(); - }); - }).rejects.toThrow( - 'Objects are not valid as a React child (found: object with keys {render}).', - ); - }).toErrorDev( - 'Warning: The component appears to be a function component that returns a class instance. ' + - 'Change Child to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`Child.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", - ); - - expect(el.textContent).toBe(''); - }); - } else { - it('should support module pattern components', () => { - function Child({test}) { - return { - render() { - return
{test}
; - }, - }; - } - - const el = document.createElement('div'); - const root = ReactDOMClient.createRoot(el); - expect(() => { - ReactDOM.flushSync(() => { + await act(() => { root.render(); }); - }).toErrorDev( - 'Warning: The component appears to be a function component that returns a class instance. ' + - 'Change Child to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`Child.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", + }).rejects.toThrow( + 'Objects are not valid as a React child (found: object with keys {render}).', ); + }).toErrorDev( + 'Warning: The component appears to be a function component that returns a class instance. ' + + 'Change Child to a class that extends React.Component instead. ' + + "If you can't use a class try assigning the prototype on the function as a workaround. " + + '`Child.prototype = React.Component.prototype`. ' + + "Don't use an arrow function since it cannot be called with `new` by React.", + ); - expect(el.textContent).toBe('test'); - }); - } - + expect(el.textContent).toBe(''); + }); it('should use default values for undefined props', async () => { class Component extends React.Component { static defaultProps = {prop: 'testKey'}; diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js index a1d3d28533fe9..ecb30f0f1d78e 100644 --- a/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js +++ b/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js @@ -527,72 +527,6 @@ describe('ReactCompositeComponent-state', () => { ]); }); - if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) { - it('should support stateful module pattern components', async () => { - function Child() { - return { - state: { - count: 123, - }, - render() { - return
{`count:${this.state.count}`}
; - }, - }; - } - - const el = document.createElement('div'); - const root = ReactDOMClient.createRoot(el); - expect(() => { - ReactDOM.flushSync(() => { - root.render(); - }); - }).toErrorDev( - 'Warning: The component appears to be a function component that returns a class instance. ' + - 'Change Child to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`Child.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", - ); - - expect(el.textContent).toBe('count:123'); - }); - - it('should support getDerivedStateFromProps for module pattern components', async () => { - function Child() { - return { - state: { - count: 1, - }, - render() { - return
{`count:${this.state.count}`}
; - }, - }; - } - Child.getDerivedStateFromProps = (props, prevState) => { - return { - count: prevState.count + props.incrementBy, - }; - }; - - const el = document.createElement('div'); - const root = ReactDOMClient.createRoot(el); - await act(() => { - root.render(); - }); - - expect(el.textContent).toBe('count:1'); - await act(() => { - root.render(); - }); - expect(el.textContent).toBe('count:3'); - - await act(() => { - root.render(); - }); - expect(el.textContent).toBe('count:4'); - }); - } - it('should not support setState in componentWillUnmount', async () => { let subscription; class A extends React.Component { diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationElements-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationElements-test.js index a66cd12cd9178..f492aebb455db 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationElements-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationElements-test.js @@ -627,23 +627,9 @@ describe('ReactDOMServerIntegration', () => { checkFooDiv(await render()); }); - if (require('shared/ReactFeatureFlags').disableModulePatternComponents) { - itThrowsWhenRendering( - 'factory components', - async render => { - const FactoryComponent = () => { - return { - render: function () { - return
foo
; - }, - }; - }; - await render(, 1); - }, - 'Objects are not valid as a React child (found: object with keys {render})', - ); - } else { - itRenders('factory components', async render => { + itThrowsWhenRendering( + 'factory components', + async render => { const FactoryComponent = () => { return { render: function () { @@ -651,9 +637,10 @@ describe('ReactDOMServerIntegration', () => { }, }; }; - checkFooDiv(await render(, 1)); - }); - } + await render(, 1); + }, + 'Objects are not valid as a React child (found: object with keys {render})', + ); }); describe('component hierarchies', function () { diff --git a/packages/react-dom/src/__tests__/ReactErrorBoundaries-test.internal.js b/packages/react-dom/src/__tests__/ReactErrorBoundaries-test.internal.js index 36a227c0fabab..ffa923de3de58 100644 --- a/packages/react-dom/src/__tests__/ReactErrorBoundaries-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactErrorBoundaries-test.internal.js @@ -879,56 +879,6 @@ describe('ReactErrorBoundaries', () => { expect(container.firstChild.textContent).toBe('Caught an error: Hello.'); }); - // @gate !disableModulePatternComponents - it('renders an error state if module-style context provider throws in componentWillMount', async () => { - function BrokenComponentWillMountWithContext() { - return { - getChildContext() { - return {foo: 42}; - }, - render() { - return
{this.props.children}
; - }, - UNSAFE_componentWillMount() { - throw new Error('Hello'); - }, - }; - } - BrokenComponentWillMountWithContext.childContextTypes = { - foo: PropTypes.number, - }; - - const container = document.createElement('div'); - const root = ReactDOMClient.createRoot(container); - - await expect(async () => { - await act(() => { - root.render( - - - , - ); - }); - }).toErrorDev([ - 'Warning: The component appears to be a function component that ' + - 'returns a class instance. ' + - 'Change BrokenComponentWillMountWithContext to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`BrokenComponentWillMountWithContext.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", - ...gate(flags => - flags.disableLegacyContext - ? [ - 'Warning: BrokenComponentWillMountWithContext uses the legacy childContextTypes API which was removed in React 19. Use React.createContext() instead.', - 'Warning: BrokenComponentWillMountWithContext uses the legacy childContextTypes API which was removed in React 19. Use React.createContext() instead.', - ] - : [], - ), - ]); - - expect(container.firstChild.textContent).toBe('Caught an error: Hello.'); - }); - it('mounts the error message if mounting fails', async () => { function renderError(error) { return ; diff --git a/packages/react-dom/src/__tests__/ReactLegacyErrorBoundaries-test.internal.js b/packages/react-dom/src/__tests__/ReactLegacyErrorBoundaries-test.internal.js index 8c53de16bf814..b0b223dd43bee 100644 --- a/packages/react-dom/src/__tests__/ReactLegacyErrorBoundaries-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactLegacyErrorBoundaries-test.internal.js @@ -849,54 +849,6 @@ describe('ReactLegacyErrorBoundaries', () => { expect(container.firstChild.textContent).toBe('Caught an error: Hello.'); }); - if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) { - // @gate !disableLegacyMode - it('renders an error state if module-style context provider throws in componentWillMount', () => { - function BrokenComponentWillMountWithContext() { - return { - getChildContext() { - return {foo: 42}; - }, - render() { - return
{this.props.children}
; - }, - UNSAFE_componentWillMount() { - throw new Error('Hello'); - }, - }; - } - BrokenComponentWillMountWithContext.childContextTypes = { - foo: PropTypes.number, - }; - - const container = document.createElement('div'); - expect(() => - ReactDOM.render( - - - , - container, - ), - ).toErrorDev([ - 'Warning: The component appears to be a function component that ' + - 'returns a class instance. ' + - 'Change BrokenComponentWillMountWithContext to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`BrokenComponentWillMountWithContext.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", - ...gate(flags => - flags.disableLegacyContext - ? [ - 'Warning: BrokenComponentWillMountWithContext uses the legacy childContextTypes API which was removed in React 19. Use React.createContext() instead.', - 'Warning: BrokenComponentWillMountWithContext uses the legacy childContextTypes API which was removed in React 19. Use React.createContext() instead.', - ] - : [], - ), - ]); - expect(container.firstChild.textContent).toBe('Caught an error: Hello.'); - }); - } - // @gate !disableLegacyMode it('mounts the error message if mounting fails', () => { function renderError(error) { diff --git a/packages/react-dom/src/__tests__/refs-test.js b/packages/react-dom/src/__tests__/refs-test.js index f43ada19e004f..4a638ef17c566 100644 --- a/packages/react-dom/src/__tests__/refs-test.js +++ b/packages/react-dom/src/__tests__/refs-test.js @@ -11,7 +11,6 @@ let React = require('react'); let ReactDOMClient = require('react-dom/client'); -let ReactFeatureFlags = require('shared/ReactFeatureFlags'); let act = require('internal-test-utils').act; // This is testing if string refs are deleted from `instance.refs` @@ -24,7 +23,6 @@ describe('reactiverefs', () => { jest.resetModules(); React = require('react'); ReactDOMClient = require('react-dom/client'); - ReactFeatureFlags = require('shared/ReactFeatureFlags'); act = require('internal-test-utils').act; }); @@ -195,38 +193,6 @@ describe('reactiverefs', () => { }); }); -if (!ReactFeatureFlags.disableModulePatternComponents) { - describe('factory components', () => { - it('Should correctly get the ref', async () => { - function Comp() { - return { - elemRef: React.createRef(), - render() { - return
; - }, - }; - } - - let inst; - await expect(async () => { - const container = document.createElement('div'); - const root = ReactDOMClient.createRoot(container); - - await act(() => { - root.render( (inst = current)} />); - }); - }).toErrorDev( - 'Warning: The component appears to be a function component that returns a class instance. ' + - 'Change Comp to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`Comp.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", - ); - expect(inst.elemRef.current.tagName).toBe('DIV'); - }); - }); -} - /** * Tests that when a ref hops around children, we can track that correctly. */ @@ -236,7 +202,6 @@ describe('ref swapping', () => { jest.resetModules(); React = require('react'); ReactDOMClient = require('react-dom/client'); - ReactFeatureFlags = require('shared/ReactFeatureFlags'); act = require('internal-test-utils').act; RefHopsAround = class extends React.Component { diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index c53e01d4ec2c6..f6dce003e842f 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -95,7 +95,6 @@ import ReactSharedInternals from 'shared/ReactSharedInternals'; import { debugRenderPhaseSideEffectsForStrictMode, disableLegacyContext, - disableModulePatternComponents, enableProfilerCommitHooks, enableProfilerTimer, enableScopeAPI, @@ -236,7 +235,6 @@ import { queueHydrationError, } from './ReactFiberHydrationContext'; import { - adoptClassInstance, constructClassInstance, mountClassInstance, resumeMountClassInstance, @@ -1920,88 +1918,27 @@ function mountIndeterminateComponent( } } - if ( - // Run these checks in production only if the flag is off. - // Eventually we'll delete this branch altogether. - !disableModulePatternComponents && - typeof value === 'object' && - value !== null && - typeof value.render === 'function' && - value.$$typeof === undefined - ) { - if (__DEV__) { - const componentName = getComponentNameFromType(Component) || 'Unknown'; - if (!didWarnAboutModulePatternComponent[componentName]) { - console.error( - 'The <%s /> component appears to be a function component that returns a class instance. ' + - 'Change %s to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + - 'cannot be called with `new` by React.', - componentName, - componentName, - componentName, - ); - didWarnAboutModulePatternComponent[componentName] = true; - } - } - - // Proceed under the assumption that this is a class instance - workInProgress.tag = ClassComponent; - - // Throw out any hooks that were used. - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; - - // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. - let hasContext = false; - if (isLegacyContextProvider(Component)) { - hasContext = true; - pushLegacyContextProvider(workInProgress); - } else { - hasContext = false; - } - - workInProgress.memoizedState = - value.state !== null && value.state !== undefined ? value.state : null; - - initializeUpdateQueue(workInProgress); - - adoptClassInstance(workInProgress, value); - mountClassInstance(workInProgress, Component, props, renderLanes); - return finishClassComponent( - null, - workInProgress, - Component, - true, - hasContext, - renderLanes, - ); - } else { - // Proceed under the assumption that this is a function component - workInProgress.tag = FunctionComponent; - if (__DEV__) { - if (disableLegacyContext && Component.contextTypes) { - console.error( - '%s uses the legacy contextTypes API which was removed in React 19. ' + - 'Use React.createContext() with React.useContext() instead.', - getComponentNameFromType(Component) || 'Unknown', - ); - } + // Proceed under the assumption that this is a function component + workInProgress.tag = FunctionComponent; + if (__DEV__) { + if (disableLegacyContext && Component.contextTypes) { + console.error( + '%s uses the legacy contextTypes API which was removed in React 19. ' + + 'Use React.createContext() with React.useContext() instead.', + getComponentNameFromType(Component) || 'Unknown', + ); } + } - if (getIsHydrating() && hasId) { - pushMaterializedTreeId(workInProgress); - } + if (getIsHydrating() && hasId) { + pushMaterializedTreeId(workInProgress); + } - reconcileChildren(null, workInProgress, value, renderLanes); - if (__DEV__) { - validateFunctionComponentInDev(workInProgress, Component); - } - return workInProgress.child; + reconcileChildren(null, workInProgress, value, renderLanes); + if (__DEV__) { + validateFunctionComponentInDev(workInProgress, Component); } + return workInProgress.child; } function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) { diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js index 231e6a3508e4e..b64f9f9e626c8 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.js @@ -1230,7 +1230,6 @@ function updateClassInstance( } export { - adoptClassInstance, constructClassInstance, mountClassInstance, resumeMountClassInstance, diff --git a/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js b/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js index 5bfa66d66fab9..b63a8b23476e4 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js @@ -1308,16 +1308,6 @@ describe('ReactHooks', () => { return
; }); - function Factory() { - return { - state: {}, - render() { - renderCount++; - return
; - }, - }; - } - let renderer; await act(() => { renderer = ReactTestRenderer.create(null, {unstable_isConcurrent: true}); @@ -1410,46 +1400,6 @@ describe('ReactHooks', () => { }); expect(renderCount).toBe(__DEV__ ? 2 : 1); - if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) { - renderCount = 0; - await expect(async () => { - await act(() => { - renderer.update(); - }); - }).toErrorDev( - 'Warning: The component appears to be a function component that returns a class instance. ' + - 'Change Factory to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`Factory.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", - ); - expect(renderCount).toBe(1); - renderCount = 0; - await act(() => { - renderer.update(); - }); - expect(renderCount).toBe(1); - - renderCount = 0; - await act(() => { - renderer.update( - - - , - ); - }); - expect(renderCount).toBe(__DEV__ ? 2 : 1); // Treated like a class - renderCount = 0; - await act(() => { - renderer.update( - - - , - ); - }); - expect(renderCount).toBe(__DEV__ ? 2 : 1); // Treated like a class - } - renderCount = 0; await act(() => { renderer.update(); diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js index 45b223e8106a4..04e7be86c61cf 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js @@ -227,44 +227,6 @@ describe('ReactHooksWithNoopRenderer', () => { await waitForAll([10]); }); - // @gate !disableModulePatternComponents - it('throws inside module-style components', async () => { - function Counter() { - return { - render() { - const [count] = useState(0); - return ; - }, - }; - } - ReactNoop.render(); - await expect( - async () => - await waitForThrow( - 'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen ' + - 'for one of the following reasons:\n' + - '1. You might have mismatching versions of React and the renderer (such as React DOM)\n' + - '2. You might be breaking the Rules of Hooks\n' + - '3. You might have more than one copy of React in the same app\n' + - 'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.', - ), - ).toErrorDev( - 'Warning: The component appears to be a function component that returns a class instance. ' + - 'Change Counter to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`Counter.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", - ); - - // Confirm that a subsequent hook works properly. - function GoodCounter(props) { - const [count] = useState(props.initialCount); - return ; - } - ReactNoop.render(); - await waitForAll([10]); - }); - it('throws when called outside the render phase', async () => { expect(() => { expect(() => useState(0)).toThrow( diff --git a/packages/react-reconciler/src/__tests__/ReactIncremental-test.js b/packages/react-reconciler/src/__tests__/ReactIncremental-test.js index 13f904bf9d014..4beb0a12dabb2 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncremental-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncremental-test.js @@ -1864,48 +1864,6 @@ describe('ReactIncremental', () => { ]); }); - // @gate !disableModulePatternComponents - // @gate !disableLegacyContext - it('does not leak own context into context provider (factory components)', async () => { - function Recurse(props, context) { - return { - getChildContext() { - return {n: (context.n || 3) - 1}; - }, - render() { - Scheduler.log('Recurse ' + JSON.stringify(context)); - if (context.n === 0) { - return null; - } - return ; - }, - }; - } - Recurse.contextTypes = { - n: PropTypes.number, - }; - Recurse.childContextTypes = { - n: PropTypes.number, - }; - - ReactNoop.render(); - await expect( - async () => - await waitForAll([ - 'Recurse {}', - 'Recurse {"n":2}', - 'Recurse {"n":1}', - 'Recurse {"n":0}', - ]), - ).toErrorDev([ - 'Warning: The component appears to be a function component that returns a class instance. ' + - 'Change Recurse to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`Recurse.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", - ]); - }); - // @gate www // @gate !disableLegacyContext it('provides context when reusing work', async () => { diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js index 6d86507d5bdec..c6e342871b198 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js @@ -1754,45 +1754,6 @@ describe('ReactIncrementalErrorHandling', () => { ); }); - // @gate !disableModulePatternComponents - it('handles error thrown inside getDerivedStateFromProps of a module-style context provider', async () => { - function Provider() { - return { - getChildContext() { - return {foo: 'bar'}; - }, - render() { - return 'Hi'; - }, - }; - } - Provider.childContextTypes = { - x: () => {}, - }; - Provider.getDerivedStateFromProps = () => { - throw new Error('Oops!'); - }; - - ReactNoop.render(); - await expect(async () => { - await waitForThrow('Oops!'); - }).toErrorDev([ - 'Warning: The component appears to be a function component that returns a class instance. ' + - 'Change Provider to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - '`Provider.prototype = React.Component.prototype`. ' + - "Don't use an arrow function since it cannot be called with `new` by React.", - ...gate(flags => - flags.disableLegacyContext - ? [ - 'Warning: Provider uses the legacy childContextTypes API which was removed in React 19. Use React.createContext() instead.', - 'Warning: Provider uses the legacy childContextTypes API which was removed in React 19. Use React.createContext() instead.', - ] - : [], - ), - ]); - }); - it('uncaught errors should be discarded if the render is aborted', async () => { const root = ReactNoop.createRoot(); diff --git a/packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js b/packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js index ed8c56072a217..c1e5f308b2202 100644 --- a/packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js +++ b/packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js @@ -1639,54 +1639,6 @@ describe('ReactFreshIntegration', () => { } }); - if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) { - it('remounts deprecated factory components', async () => { - if (__DEV__) { - await expect(async () => { - await render(` - function Parent() { - return { - render() { - return ; - } - }; - }; - - function Child({prop}) { - return

{prop}1

; - }; - - export default Parent; - `); - }).toErrorDev( - 'The component appears to be a function component ' + - 'that returns a class instance.', - ); - const el = container.firstChild; - expect(el.textContent).toBe('A1'); - await patch(` - function Parent() { - return { - render() { - return ; - } - }; - }; - - function Child({prop}) { - return

{prop}2

; - }; - - export default Parent; - `); - // Like classes, factory components always remount. - expect(container.firstChild).not.toBe(el); - const newEl = container.firstChild; - expect(newEl.textContent).toBe('B2'); - } - }); - } - describe('with inline requires', () => { beforeEach(() => { global.FakeModuleSystem = {}; diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index c66608414d900..f49fca69b6485 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -137,7 +137,6 @@ import { import ReactSharedInternals from 'shared/ReactSharedInternals'; import { disableLegacyContext, - disableModulePatternComponents, enableBigIntSupport, enableScopeAPI, enableSuspenseAvoidThisFallbackFizz, @@ -1469,58 +1468,28 @@ function renderIndeterminateComponent( } } - if ( - // Run these checks in production only if the flag is off. - // Eventually we'll delete this branch altogether. - !disableModulePatternComponents && - typeof value === 'object' && - value !== null && - typeof value.render === 'function' && - value.$$typeof === undefined - ) { - if (__DEV__) { - const componentName = getComponentNameFromType(Component) || 'Unknown'; - if (!didWarnAboutModulePatternComponent[componentName]) { - console.error( - 'The <%s /> component appears to be a function component that returns a class instance. ' + - 'Change %s to a class that extends React.Component instead. ' + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + - 'cannot be called with `new` by React.', - componentName, - componentName, - componentName, - ); - didWarnAboutModulePatternComponent[componentName] = true; - } - } - - mountClassInstance(value, Component, props, legacyContext); - finishClassComponent(request, task, keyPath, value, Component, props); - } else { - // Proceed under the assumption that this is a function component - if (__DEV__) { - if (disableLegacyContext && Component.contextTypes) { - console.error( - '%s uses the legacy contextTypes API which was removed in React 19. ' + - 'Use React.createContext() with React.useContext() instead.', - getComponentNameFromType(Component) || 'Unknown', - ); - } - } - if (__DEV__) { - validateFunctionComponentInDev(Component); + // Proceed under the assumption that this is a function component + if (__DEV__) { + if (disableLegacyContext && Component.contextTypes) { + console.error( + '%s uses the legacy contextTypes API which was removed in React 19. ' + + 'Use React.createContext() with React.useContext() instead.', + getComponentNameFromType(Component) || 'Unknown', + ); } - finishFunctionComponent( - request, - task, - keyPath, - value, - hasId, - actionStateCount, - actionStateMatchingIndex, - ); } + if (__DEV__) { + validateFunctionComponentInDev(Component); + } + finishFunctionComponent( + request, + task, + keyPath, + value, + hasId, + actionStateCount, + actionStateMatchingIndex, + ); task.componentStack = previousComponentStack; } diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 9747dd38f6691..3861ea5b6329c 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -206,8 +206,6 @@ export const enableRenderableContext = __NEXT_MAJOR__; // when we plan to enable them. // ----------------------------------------------------------------------------- -export const disableModulePatternComponents = __NEXT_MAJOR__; - export const enableUseRefAccessWarning = false; // Enables time slicing for updates that aren't wrapped in startTransition. diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index e51541b1bb93d..1c6180ae903ae 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -34,7 +34,6 @@ export const { } = dynamicFlags; // The rest of the flags are static for better dead code elimination. -export const disableModulePatternComponents = true; export const enableDebugTracing = false; export const enableAsyncDebugInfo = false; export const enableSchedulingProfiler = __PROFILE__; diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index d447207b98e80..1c3a95b52c40b 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -31,7 +31,6 @@ export const enableDeferRootSchedulingToMicrotask = __TODO_NEXT_RN_MAJOR__; export const alwaysThrottleRetries = __TODO_NEXT_RN_MAJOR__; export const enableInfiniteRenderLoopDetection = __TODO_NEXT_RN_MAJOR__; export const enableComponentStackLocations = __TODO_NEXT_RN_MAJOR__; -export const disableModulePatternComponents = __TODO_NEXT_RN_MAJOR__; // ----------------------------------------------------------------------------- // These are ready to flip after the next React npm release (or RN switches to diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index bce10070683f6..d5b60e8203396 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -94,7 +94,6 @@ export const disableLegacyMode = __NEXT_MAJOR__; export const disableLegacyContext = __NEXT_MAJOR__; export const disableDOMTestUtils = __NEXT_MAJOR__; export const enableNewBooleanProps = __NEXT_MAJOR__; -export const disableModulePatternComponents = __NEXT_MAJOR__; export const enableRenderableContext = __NEXT_MAJOR__; export const enableReactTestRendererWarning = __NEXT_MAJOR__; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js index b184d47d8fe3a..710eeb607ebfb 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js @@ -34,7 +34,6 @@ export const enableSuspenseCallback = false; export const disableLegacyContext = false; export const enableTrustedTypesIntegration = false; export const disableTextareaChildren = false; -export const disableModulePatternComponents = true; export const enableComponentStackLocations = false; export const enableLegacyFBSupport = false; export const enableFilterEmptyStringAttributesDOM = true; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index 87b5e0302aea2..a4a3c138a218d 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -34,7 +34,6 @@ export const enableSuspenseCallback = true; export const disableLegacyContext = false; export const enableTrustedTypesIntegration = false; export const disableTextareaChildren = false; -export const disableModulePatternComponents = true; export const enableSuspenseAvoidThisFallback = true; export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = false; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 92c3eb0b38653..c309500c3f00b 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -82,8 +82,6 @@ export const enablePostpone = false; // Need to remove it. export const disableCommentsAsDOMContainers = false; -export const disableModulePatternComponents = true; - export const enableCreateEventHandleAPI = true; export const enableScopeAPI = true;