diff --git a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
index d07ab9e71b0b3..d3a395d4f2d12 100644
--- a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
+++ b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
@@ -1114,72 +1114,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..341dd05468b0c 100644
--- a/packages/react-dom/src/__tests__/refs-test.js
+++ b/packages/react-dom/src/__tests__/refs-test.js
@@ -195,38 +195,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.
*/
diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js
index c53e01d4ec2c6..3328b9367942f 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,
@@ -1920,88 +1919,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/__tests__/ReactHooks-test.internal.js b/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js
index 5bfa66d66fab9..32479144270d1 100644
--- a/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js
+++ b/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js
@@ -1410,46 +1410,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;