diff --git a/packages/react-art/npm/Circle.js b/packages/react-art/npm/Circle.js index 06bbf3d836ead..e27b473dcb7cf 100644 --- a/packages/react-art/npm/Circle.js +++ b/packages/react-art/npm/Circle.js @@ -18,7 +18,6 @@ 'use strict'; var assign = Object.assign; -var PropTypes = require('prop-types'); var React = require('react'); var ReactART = require('react-art'); @@ -34,10 +33,6 @@ var Shape = ReactART.Shape; var Circle = createReactClass({ displayName: 'Circle', - propTypes: { - radius: PropTypes.number.isRequired, - }, - render: function render() { var radius = this.props.radius; diff --git a/packages/react-art/npm/Rectangle.js b/packages/react-art/npm/Rectangle.js index ae85ccba393c4..c71eeaf06d09d 100644 --- a/packages/react-art/npm/Rectangle.js +++ b/packages/react-art/npm/Rectangle.js @@ -25,7 +25,6 @@ 'use strict'; var assign = Object.assign; -var PropTypes = require('prop-types'); var React = require('react'); var ReactART = require('react-art'); @@ -41,16 +40,6 @@ var Path = ReactART.Path; var Rectangle = createReactClass({ displayName: 'Rectangle', - propTypes: { - width: PropTypes.number.isRequired, - height: PropTypes.number.isRequired, - radius: PropTypes.number, - radiusTopLeft: PropTypes.number, - radiusTopRight: PropTypes.number, - radiusBottomRight: PropTypes.number, - radiusBottomLeft: PropTypes.number, - }, - render: function render() { var width = this.props.width; var height = this.props.height; diff --git a/packages/react-art/npm/Wedge.js b/packages/react-art/npm/Wedge.js index e1323e4ae44b9..333cd22834185 100644 --- a/packages/react-art/npm/Wedge.js +++ b/packages/react-art/npm/Wedge.js @@ -21,7 +21,6 @@ 'use strict'; var assign = Object.assign; -var PropTypes = require('prop-types'); var React = require('react'); var ReactART = require('react-art'); @@ -37,13 +36,6 @@ var Path = ReactART.Path; var Wedge = createReactClass({ displayName: 'Wedge', - propTypes: { - outerRadius: PropTypes.number.isRequired, - startAngle: PropTypes.number.isRequired, - endAngle: PropTypes.number.isRequired, - innerRadius: PropTypes.number, - }, - circleRadians: Math.PI * 2, radiansPerDegree: Math.PI / 180, diff --git a/packages/react-art/src/__tests__/ReactART-test.js b/packages/react-art/src/__tests__/ReactART-test.js index 063c8df8244c5..bb56e6d42d73f 100644 --- a/packages/react-art/src/__tests__/ReactART-test.js +++ b/packages/react-art/src/__tests__/ReactART-test.js @@ -461,18 +461,6 @@ describe('ReactARTComponents', () => { expect(circle.toJSON()).toMatchSnapshot(); }); - it('should warn if radius is missing on a Circle component', () => { - expect(() => - ReactTestRenderer.create( - , - ), - ).toErrorDev( - 'Warning: Failed prop type: The prop `radius` is marked as required in `Circle`, ' + - 'but its value is `undefined`.' + - '\n in Circle (at **)', - ); - }); - it('should generate a with props for drawing the Rectangle', () => { const rectangle = ReactTestRenderer.create( , @@ -534,19 +522,6 @@ describe('ReactARTComponents', () => { expect(rectangle.toJSON()).toMatchSnapshot(); }); - it('should warn if width/height is missing on a Rectangle component', () => { - expect(() => - ReactTestRenderer.create(), - ).toErrorDev([ - 'Warning: Failed prop type: The prop `width` is marked as required in `Rectangle`, ' + - 'but its value is `undefined`.' + - '\n in Rectangle (at **)', - 'Warning: Failed prop type: The prop `height` is marked as required in `Rectangle`, ' + - 'but its value is `undefined`.' + - '\n in Rectangle (at **)', - ]); - }); - it('should generate a with props for drawing the Wedge', () => { const wedge = ReactTestRenderer.create( , @@ -560,18 +535,4 @@ describe('ReactARTComponents', () => { ); expect(wedge.toJSON()).toBeNull(); }); - - it('should warn if outerRadius/startAngle/endAngle is missing on a Wedge component', () => { - expect(() => ReactTestRenderer.create()).toErrorDev([ - 'Warning: Failed prop type: The prop `outerRadius` is marked as required in `Wedge`, ' + - 'but its value is `undefined`.' + - '\n in Wedge (at **)', - 'Warning: Failed prop type: The prop `startAngle` is marked as required in `Wedge`, ' + - 'but its value is `undefined`.' + - '\n in Wedge (at **)', - 'Warning: Failed prop type: The prop `endAngle` is marked as required in `Wedge`, ' + - 'but its value is `undefined`.' + - '\n in Wedge (at **)', - ]); - }); }); diff --git a/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js b/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js index fffca3675a711..bd44b56b9d494 100644 --- a/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js @@ -386,13 +386,9 @@ describe('ReactFunctionComponent', () => { return
{props.test}
; } Child.defaultProps = {test: 2}; - Child.propTypes = {test: PropTypes.string}; expect(() => ReactTestUtils.renderIntoDocument()).toErrorDev([ 'Warning: Child: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.', - 'Warning: Failed prop type: Invalid prop `test` of type `number` ' + - 'supplied to `Child`, expected `string`.\n' + - ' in Child (at **)', ]); }); diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 4a333ad782f1b..e050580390847 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -40,7 +40,6 @@ import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent'; import type {TransitionStatus} from './ReactFiberConfig'; import type {Hook} from './ReactFiberHooks'; -import checkPropTypes from 'shared/checkPropTypes'; import { markComponentRenderStarted, markComponentRenderStopped, @@ -401,22 +400,6 @@ function updateForwardRef( // hasn't yet mounted. This happens after the first render suspends. // We'll need to figure out if this is fine or can cause issues. - if (__DEV__) { - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - const innerPropTypes = Component.propTypes; - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - 'prop', - getComponentNameFromType(Component), - ); - } - } - } - const render = Component.render; const ref = workInProgress.ref; @@ -506,17 +489,6 @@ function updateMemoComponent( ); } if (__DEV__) { - const innerPropTypes = type.propTypes; - if (innerPropTypes) { - // Inner memo component props aren't currently validated in createElement. - // We could move it there, but we'd still need this for lazy code path. - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - 'prop', - getComponentNameFromType(type), - ); - } if (Component.defaultProps !== undefined) { const componentName = getComponentNameFromType(type) || 'Unknown'; if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { @@ -542,20 +514,6 @@ function updateMemoComponent( workInProgress.child = child; return child; } - if (__DEV__) { - const type = Component.type; - const innerPropTypes = type.propTypes; - if (innerPropTypes) { - // Inner memo component props aren't currently validated in createElement. - // We could move it there, but we'd still need this for lazy code path. - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - 'prop', - getComponentNameFromType(type), - ); - } - } const currentChild = ((current.child: any): Fiber); // This is always exactly one child const hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( current, @@ -591,37 +549,6 @@ function updateSimpleMemoComponent( // TODO: current can be non-null here even if the component // hasn't yet mounted. This happens when the inner render suspends. // We'll need to figure out if this is fine or can cause issues. - - if (__DEV__) { - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - let outerMemoType = workInProgress.elementType; - if (outerMemoType.$$typeof === REACT_LAZY_TYPE) { - // We warn when you define propTypes on lazy() - // so let's just skip over it to find memo() outer wrapper. - // Inner props for memo are validated later. - const lazyComponent: LazyComponentType = outerMemoType; - const payload = lazyComponent._payload; - const init = lazyComponent._init; - try { - outerMemoType = init(payload); - } catch (x) { - outerMemoType = null; - } - // Inner propTypes will be validated in the function component path. - const outerPropTypes = outerMemoType && (outerMemoType: any).propTypes; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - nextProps, // Resolved (SimpleMemoComponent has no defaultProps) - 'prop', - getComponentNameFromType(outerMemoType), - ); - } - } - } - } if (current !== null) { const prevProps = current.memoizedProps; if ( @@ -1098,22 +1025,6 @@ function updateFunctionComponent( nextProps: any, renderLanes: Lanes, ) { - if (__DEV__) { - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - const innerPropTypes = Component.propTypes; - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - 'prop', - getComponentNameFromType(Component), - ); - } - } - } - let context; if (!disableLegacyContext) { const unmaskedContext = getUnmaskedContext(workInProgress, Component, true); @@ -1252,20 +1163,6 @@ function updateClassComponent( break; } } - - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - const innerPropTypes = Component.propTypes; - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - 'prop', - getComponentNameFromType(Component), - ); - } - } } // Push context providers early to prevent context stack mismatches. @@ -1814,19 +1711,6 @@ function mountLazyComponent( return child; } case MemoComponent: { - if (__DEV__) { - if (workInProgress.type !== workInProgress.elementType) { - const outerPropTypes = Component.propTypes; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - resolvedProps, // Resolved for outer only - 'prop', - getComponentNameFromType(Component), - ); - } - } - } child = updateMemoComponent( null, workInProgress, @@ -3545,13 +3429,7 @@ function updateContextProvider( ); } } - const providerPropTypes = workInProgress.type.propTypes; - - if (providerPropTypes) { - checkPropTypes(providerPropTypes, newProps, 'prop', 'Context.Provider'); - } } - pushProvider(workInProgress, context, newValue); if (enableLazyContextPropagation) { @@ -4232,19 +4110,6 @@ function beginWork( const unresolvedProps = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. let resolvedProps = resolveDefaultProps(type, unresolvedProps); - if (__DEV__) { - if (workInProgress.type !== workInProgress.elementType) { - const outerPropTypes = type.propTypes; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - resolvedProps, // Resolved for outer only - 'prop', - getComponentNameFromType(type), - ); - } - } - } resolvedProps = resolveDefaultProps(type.type, resolvedProps); return updateMemoComponent( current, diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js index cceb78c8ed878..f4892cc14c6ae 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.js @@ -395,13 +395,6 @@ function checkClassInstance(workInProgress: Fiber, ctor: any, newProps: any) { name, ); } - if (instance.propTypes) { - console.error( - 'propTypes was defined as an instance property on %s. Use a static ' + - 'property to define propTypes instead.', - name, - ); - } if (instance.contextType) { console.error( 'contextType was defined as an instance property on %s. Use a static ' + diff --git a/packages/react-reconciler/src/ReactFiberContext.js b/packages/react-reconciler/src/ReactFiberContext.js index ea8fdfd67f7ff..49a3d6a5c9602 100644 --- a/packages/react-reconciler/src/ReactFiberContext.js +++ b/packages/react-reconciler/src/ReactFiberContext.js @@ -14,7 +14,7 @@ import {isFiberMounted} from './ReactFiberTreeReflection'; import {disableLegacyContext} from 'shared/ReactFeatureFlags'; import {ClassComponent, HostRoot} from './ReactWorkTags'; import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber'; -import checkPropTypes from 'shared/checkPropTypes'; +import checkContextPropTypes from 'shared/checkContextPropTypes'; import {createCursor, push, pop} from './ReactFiberStack'; @@ -103,7 +103,7 @@ function getMaskedContext( if (__DEV__) { const name = getComponentNameFromFiber(workInProgress) || 'Unknown'; - checkPropTypes(contextTypes, context, 'context', name); + checkContextPropTypes(contextTypes, context, 'context', name); } // Cache unmasked context so we can avoid recreating masked context unless necessary. @@ -214,7 +214,12 @@ function processChildContext( } if (__DEV__) { const name = getComponentNameFromFiber(fiber) || 'Unknown'; - checkPropTypes(childContextTypes, childContext, 'child context', name); + checkContextPropTypes( + childContextTypes, + childContext, + 'child context', + name, + ); } return {...parentContext, ...childContext}; diff --git a/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js b/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js index 36e956256dc60..95d34492345de 100644 --- a/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js @@ -1,4 +1,3 @@ -let PropTypes; let React; let ReactTestRenderer; let Scheduler; @@ -28,7 +27,6 @@ describe('ReactLazy', () => { ReactFeatureFlags = require('shared/ReactFeatureFlags'); ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false; - PropTypes = require('prop-types'); React = require('react'); Suspense = React.Suspense; lazy = React.lazy; @@ -783,32 +781,12 @@ describe('ReactLazy', () => { ); }); - it('warns about defining propTypes on the outer wrapper', () => { - const LazyText = lazy(() => fakeImport(Text)); - expect(() => { - LazyText.propTypes = {hello: () => {}}; - }).toErrorDev( - 'React.lazy(...): It is not supported to assign `propTypes` to ' + - 'a lazy component import. Either specify them where the component ' + - 'is defined, or create a wrapping component around it.', - {withoutStack: true}, - ); - }); - async function verifyInnerPropTypesAreChecked( Add, shouldWarnAboutFunctionDefaultProps, shouldWarnAboutMemoDefaultProps, ) { const LazyAdd = lazy(() => fakeImport(Add)); - expect(() => { - LazyAdd.propTypes = {}; - }).toErrorDev( - 'React.lazy(...): It is not supported to assign `propTypes` to ' + - 'a lazy component import. Either specify them where the component ' + - 'is defined, or create a wrapping component around it.', - {withoutStack: true}, - ); const root = ReactTestRenderer.create( }> @@ -824,176 +802,80 @@ describe('ReactLazy', () => { expect(root).not.toMatchRenderedOutput('22'); // Mount - await expect(async () => { - await act(() => resolveFakeImport(Add)); - }).toErrorDev( - shouldWarnAboutFunctionDefaultProps - ? [ - 'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.', - 'Invalid prop `inner` of type `string` supplied to `Add`, expected `number`.', - ] - : shouldWarnAboutMemoDefaultProps - ? [ - 'Add: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.', - 'Invalid prop `inner` of type `string` supplied to `Add`, expected `number`.', - ] - : [ - 'Invalid prop `inner` of type `string` supplied to `Add`, expected `number`.', - ], - ); + await act(() => resolveFakeImport(Add)); expect(root).toMatchRenderedOutput('22'); // Update - await expect(async () => { + await act(() => { root.update( }> , ); - await waitForAll([]); - }).toErrorDev( - 'Invalid prop `inner` of type `boolean` supplied to `Add`, expected `number`.', - ); + }); expect(root).toMatchRenderedOutput('0'); } - // Note: all "with defaultProps" tests below also verify defaultProps works as expected. - // If we ever delete or move propTypes-related tests, make sure not to delete these. - it('respects propTypes on function component with defaultProps', async () => { + it('respects defaultProps on function component', async () => { function Add(props) { expect(props.innerWithDefault).toBe(42); return props.inner + props.outer; } - Add.propTypes = { - inner: PropTypes.number.isRequired, - innerWithDefault: PropTypes.number.isRequired, - }; Add.defaultProps = { innerWithDefault: 42, }; await verifyInnerPropTypesAreChecked(Add, true); }); - it('respects propTypes on function component without defaultProps', async () => { - function Add(props) { - return props.inner + props.outer; - } - Add.propTypes = { - inner: PropTypes.number.isRequired, - }; - await verifyInnerPropTypesAreChecked(Add); - }); - - it('respects propTypes on class component with defaultProps', async () => { + it('respects defaultProps on class component', async () => { class Add extends React.Component { render() { expect(this.props.innerWithDefault).toBe(42); return this.props.inner + this.props.outer; } } - Add.propTypes = { - inner: PropTypes.number.isRequired, - innerWithDefault: PropTypes.number.isRequired, - }; Add.defaultProps = { innerWithDefault: 42, }; await verifyInnerPropTypesAreChecked(Add); }); - it('respects propTypes on class component without defaultProps', async () => { - class Add extends React.Component { - render() { - return this.props.inner + this.props.outer; - } - } - Add.propTypes = { - inner: PropTypes.number.isRequired, - }; - await verifyInnerPropTypesAreChecked(Add); - }); - - it('respects propTypes on forwardRef component with defaultProps', async () => { + it('respects defaultProps on forwardRef component', async () => { const Add = React.forwardRef((props, ref) => { expect(props.innerWithDefault).toBe(42); return props.inner + props.outer; }); Add.displayName = 'Add'; - Add.propTypes = { - inner: PropTypes.number.isRequired, - innerWithDefault: PropTypes.number.isRequired, - }; Add.defaultProps = { innerWithDefault: 42, }; await verifyInnerPropTypesAreChecked(Add); }); - it('respects propTypes on forwardRef component without defaultProps', async () => { - const Add = React.forwardRef((props, ref) => { - return props.inner + props.outer; - }); - Add.displayName = 'Add'; - Add.propTypes = { - inner: PropTypes.number.isRequired, - }; - await verifyInnerPropTypesAreChecked(Add); - }); - - it('respects propTypes on outer memo component with defaultProps', async () => { + it('respects defaultProps on outer memo component', async () => { let Add = props => { expect(props.innerWithDefault).toBe(42); return props.inner + props.outer; }; Add = React.memo(Add); - Add.propTypes = { - inner: PropTypes.number.isRequired, - innerWithDefault: PropTypes.number.isRequired, - }; Add.defaultProps = { innerWithDefault: 42, }; await verifyInnerPropTypesAreChecked(Add, false, true); }); - it('respects propTypes on outer memo component without defaultProps', async () => { - let Add = props => { - return props.inner + props.outer; - }; - Add = React.memo(Add); - Add.propTypes = { - inner: PropTypes.number.isRequired, - }; - await verifyInnerPropTypesAreChecked(Add); - }); - - it('respects propTypes on inner memo component with defaultProps', async () => { + it('respects defaultProps on inner memo component', async () => { const Add = props => { expect(props.innerWithDefault).toBe(42); return props.inner + props.outer; }; Add.displayName = 'Add'; - Add.propTypes = { - inner: PropTypes.number.isRequired, - innerWithDefault: PropTypes.number.isRequired, - }; Add.defaultProps = { innerWithDefault: 42, }; await verifyInnerPropTypesAreChecked(React.memo(Add), true); }); - it('respects propTypes on inner memo component without defaultProps', async () => { - const Add = props => { - return props.inner + props.outer; - }; - Add.displayName = 'Add'; - Add.propTypes = { - inner: PropTypes.number.isRequired, - }; - await verifyInnerPropTypesAreChecked(React.memo(Add)); - }); - it('uses outer resolved props for validating propTypes on memo', async () => { let T = props => { return ; @@ -1002,10 +884,6 @@ describe('ReactLazy', () => { text: 'Inner default text', }; T = React.memo(T); - T.propTypes = { - // Should not be satisfied by the *inner* defaultProps. - text: PropTypes.string.isRequired, - }; const LazyText = lazy(() => fakeImport(T)); const root = ReactTestRenderer.create( }> @@ -1025,21 +903,16 @@ describe('ReactLazy', () => { assertLog(['Inner default text']); }).toErrorDev([ 'T: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.', - 'The prop `text` is marked as required in `T`, but its value is `undefined`', ]); expect(root).toMatchRenderedOutput('Inner default text'); // Update - await expect(async () => { - root.update( - }> - - , - ); - await waitForAll([null]); - }).toErrorDev( - 'The prop `text` is marked as required in `T`, but its value is `null`', + root.update( + }> + + , ); + await waitForAll([null]); expect(root).toMatchRenderedOutput(null); }); diff --git a/packages/react-server/src/ReactFizzClassComponent.js b/packages/react-server/src/ReactFizzClassComponent.js index e624dfa941293..7afc497463371 100644 --- a/packages/react-server/src/ReactFizzClassComponent.js +++ b/packages/react-server/src/ReactFizzClassComponent.js @@ -358,13 +358,6 @@ function checkClassInstance(instance: any, ctor: any, newProps: any) { name, ); } - if (instance.propTypes) { - console.error( - 'propTypes was defined as an instance property on %s. Use a static ' + - 'property to define propTypes instead.', - name, - ); - } if (instance.contextType) { console.error( 'contextType was defined as an instance property on %s. Use a static ' + diff --git a/packages/react-server/src/ReactFizzContext.js b/packages/react-server/src/ReactFizzContext.js index 4dcbdf39fee33..c41f2e029e08c 100644 --- a/packages/react-server/src/ReactFizzContext.js +++ b/packages/react-server/src/ReactFizzContext.js @@ -9,7 +9,7 @@ import {disableLegacyContext} from 'shared/ReactFeatureFlags'; import getComponentNameFromType from 'shared/getComponentNameFromType'; -import checkPropTypes from 'shared/checkPropTypes'; +import checkContextPropTypes from 'shared/checkContextPropTypes'; let warnedAboutMissingGetChildContext; @@ -38,7 +38,7 @@ export function getMaskedContext(type: any, unmaskedContext: Object): Object { if (__DEV__) { const name = getComponentNameFromType(type) || 'Unknown'; - checkPropTypes(contextTypes, context, 'context', name); + checkContextPropTypes(contextTypes, context, 'context', name); } return context; @@ -86,7 +86,12 @@ export function processChildContext( } if (__DEV__) { const name = getComponentNameFromType(type) || 'Unknown'; - checkPropTypes(childContextTypes, childContext, 'child context', name); + checkContextPropTypes( + childContextTypes, + childContext, + 'child context', + name, + ); } return {...parentContext, ...childContext}; diff --git a/packages/react/src/ReactElementValidator.js b/packages/react/src/ReactElementValidator.js index 275be8efe2d66..5de5dc1b8b344 100644 --- a/packages/react/src/ReactElementValidator.js +++ b/packages/react/src/ReactElementValidator.js @@ -16,12 +16,9 @@ import isValidElementType from 'shared/isValidElementType'; import getComponentNameFromType from 'shared/getComponentNameFromType'; import { getIteratorFn, - REACT_FORWARD_REF_TYPE, - REACT_MEMO_TYPE, REACT_FRAGMENT_TYPE, REACT_ELEMENT_TYPE, } from 'shared/ReactSymbols'; -import checkPropTypes from 'shared/checkPropTypes'; import isArray from 'shared/isArray'; import ReactCurrentOwner from './ReactCurrentOwner'; @@ -46,12 +43,6 @@ function setCurrentlyValidatingElement(element) { } } -let propTypesMisspellWarningShown; - -if (__DEV__) { - propTypesMisspellWarningShown = false; -} - function getDeclarationErrorAddendum() { if (ReactCurrentOwner.current) { const name = getComponentNameFromType(ReactCurrentOwner.current.type); @@ -192,60 +183,6 @@ function validateChildKeys(node, parentType) { } } -/** - * Given an element, validate that its props follow the propTypes definition, - * provided by the type. - * - * @param {ReactElement} element - */ -function validatePropTypes(element) { - if (__DEV__) { - const type = element.type; - if (type === null || type === undefined || typeof type === 'string') { - return; - } - if (type.$$typeof === REACT_CLIENT_REFERENCE) { - return; - } - let propTypes; - if (typeof type === 'function') { - propTypes = type.propTypes; - } else if ( - typeof type === 'object' && - (type.$$typeof === REACT_FORWARD_REF_TYPE || - // Note: Memo only checks outer props here. - // Inner props are checked in the reconciler. - type.$$typeof === REACT_MEMO_TYPE) - ) { - propTypes = type.propTypes; - } else { - return; - } - if (propTypes) { - // Intentionally inside to avoid triggering lazy initializers: - const name = getComponentNameFromType(type); - checkPropTypes(propTypes, element.props, 'prop', name, element); - } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) { - propTypesMisspellWarningShown = true; - // Intentionally inside to avoid triggering lazy initializers: - const name = getComponentNameFromType(type); - console.error( - 'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', - name || 'Unknown', - ); - } - if ( - typeof type.getDefaultProps === 'function' && - !type.getDefaultProps.isReactClassApproved - ) { - console.error( - 'getDefaultProps is only used on classic React.createClass ' + - 'definitions. Use a static property named `defaultProps` instead.', - ); - } - } -} - /** * Given a fragment, validate that it can only be provided with fragment props * @param {ReactElement} fragment @@ -345,8 +282,6 @@ export function createElementWithValidation(type, props, children) { if (type === REACT_FRAGMENT_TYPE) { validateFragmentProps(element); - } else { - validatePropTypes(element); } return element; @@ -390,6 +325,5 @@ export function cloneElementWithValidation(element, props, children) { for (let i = 2; i < arguments.length; i++) { validateChildKeys(arguments[i], newElement.type); } - validatePropTypes(newElement); return newElement; } diff --git a/packages/react/src/ReactForwardRef.js b/packages/react/src/ReactForwardRef.js index 4581fa9ca10a2..8e6566ac8165d 100644 --- a/packages/react/src/ReactForwardRef.js +++ b/packages/react/src/ReactForwardRef.js @@ -34,15 +34,6 @@ export function forwardRef( ); } } - - if (render != null) { - if (render.defaultProps != null || render.propTypes != null) { - console.error( - 'forwardRef render functions do not support propTypes or defaultProps. ' + - 'Did you accidentally pass a React component?', - ); - } - } } const elementType = { diff --git a/packages/react/src/ReactLazy.js b/packages/react/src/ReactLazy.js index 7c219638408e6..a01e2342ad31d 100644 --- a/packages/react/src/ReactLazy.js +++ b/packages/react/src/ReactLazy.js @@ -137,7 +137,6 @@ export function lazy( if (__DEV__) { // In production, this would just set it on the object. let defaultProps; - let propTypes; // $FlowFixMe[prop-missing] Object.defineProperties(lazyType, { defaultProps: { @@ -160,26 +159,6 @@ export function lazy( }); }, }, - propTypes: { - configurable: true, - get() { - return propTypes; - }, - // $FlowFixMe[missing-local-annot] - set(newPropTypes) { - console.error( - 'React.lazy(...): It is not supported to assign `propTypes` to ' + - 'a lazy component import. Either specify them where the component ' + - 'is defined, or create a wrapping component around it.', - ); - propTypes = newPropTypes; - // Match production behavior more closely: - // $FlowFixMe[prop-missing] - Object.defineProperty(lazyType, 'propTypes', { - enumerable: true, - }); - }, - }, }); } diff --git a/packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee b/packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee index 96bd3e0c24ca1..a137704d512bf 100644 --- a/packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee +++ b/packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee @@ -405,7 +405,6 @@ describe 'ReactCoffeeScriptClass', -> constructor: -> @contextTypes = {} @contextType = {} - @propTypes = {} getInitialState: -> getInitialStateWasCalled = true @@ -425,7 +424,6 @@ describe 'ReactCoffeeScriptClass', -> ).toErrorDev([ 'getInitialState was defined on Foo, a plain JavaScript class.', 'getDefaultProps was defined on Foo, a plain JavaScript class.', - 'propTypes was defined as an instance property on Foo.', 'contextTypes was defined as an instance property on Foo.', 'contextType was defined as an instance property on Foo.', ]) diff --git a/packages/react/src/__tests__/ReactES6Class-test.js b/packages/react/src/__tests__/ReactES6Class-test.js index 1f2d899f88207..49ed8569254a9 100644 --- a/packages/react/src/__tests__/ReactES6Class-test.js +++ b/packages/react/src/__tests__/ReactES6Class-test.js @@ -448,7 +448,6 @@ describe('ReactES6Class', () => { super(); this.contextTypes = {}; this.contextType = {}; - this.propTypes = {}; } getInitialState() { getInitialStateWasCalled = true; @@ -466,7 +465,6 @@ describe('ReactES6Class', () => { expect(() => test(, 'SPAN', 'foo')).toErrorDev([ 'getInitialState was defined on Foo, a plain JavaScript class.', 'getDefaultProps was defined on Foo, a plain JavaScript class.', - 'propTypes was defined as an instance property on Foo.', 'contextType was defined as an instance property on Foo.', 'contextTypes was defined as an instance property on Foo.', ]); diff --git a/packages/react/src/__tests__/ReactElementValidator-test.internal.js b/packages/react/src/__tests__/ReactElementValidator-test.internal.js index c32ddd3b3fcbd..38f1bdc22b1a3 100644 --- a/packages/react/src/__tests__/ReactElementValidator-test.internal.js +++ b/packages/react/src/__tests__/ReactElementValidator-test.internal.js @@ -15,7 +15,6 @@ // that do use JSX syntax. We should port them to React.createElement, and also // confirm there's a corresponding test that uses JSX syntax. -let PropTypes; let React; let ReactDOMClient; let act; @@ -28,7 +27,6 @@ describe('ReactElementValidator', () => { beforeEach(() => { jest.resetModules(); - PropTypes = require('prop-types'); ReactFeatureFlags = require('shared/ReactFeatureFlags'); ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false; React = require('react'); @@ -221,31 +219,6 @@ describe('ReactElementValidator', () => { React.createElement(ComponentClass, null, [{}, {}]); }); - it('should give context for PropType errors in nested components.', async () => { - // In this test, we're making sure that if a proptype error is found in a - // component, we give a small hint as to which parent instantiated that - // component as per warnings about key usage in ReactElementValidator. - function MyComp(props) { - return React.createElement('div', null, 'My color is ' + props.color); - } - MyComp.propTypes = { - color: PropTypes.string, - }; - function ParentComp() { - return React.createElement(MyComp, {color: 123}); - } - await expect(async () => { - const root = ReactDOMClient.createRoot(document.createElement('div')); - await act(() => root.render(React.createElement(ParentComp))); - }).toErrorDev( - 'Warning: Failed prop type: ' + - 'Invalid prop `color` of type `number` supplied to `MyComp`, ' + - 'expected `string`.\n' + - ' in MyComp (at **)\n' + - ' in ParentComp (at **)', - ); - }); - it('gives a helpful error when passing invalid types', () => { function Foo() {} expect(() => { @@ -328,125 +301,6 @@ describe('ReactElementValidator', () => { ]); }); - it('should check default prop values', async () => { - class Component extends React.Component { - static propTypes = {prop: PropTypes.string.isRequired}; - static defaultProps = {prop: null}; - render() { - return React.createElement('span', null, this.props.prop); - } - } - - await expect(async () => { - const root = ReactDOMClient.createRoot(document.createElement('div')); - await act(() => root.render(React.createElement(Component))); - }).toErrorDev( - 'Warning: Failed prop type: The prop `prop` is marked as required in ' + - '`Component`, but its value is `null`.\n' + - ' in Component', - ); - }); - - it('should not check the default for explicit null', async () => { - class Component extends React.Component { - static propTypes = {prop: PropTypes.string.isRequired}; - static defaultProps = {prop: 'text'}; - render() { - return React.createElement('span', null, this.props.prop); - } - } - - await expect(async () => { - const root = ReactDOMClient.createRoot(document.createElement('div')); - await act(() => - root.render(React.createElement(Component, {prop: null})), - ); - }).toErrorDev( - 'Warning: Failed prop type: The prop `prop` is marked as required in ' + - '`Component`, but its value is `null`.\n' + - ' in Component', - ); - }); - - it('should check declared prop types', async () => { - class Component extends React.Component { - static propTypes = { - prop: PropTypes.string.isRequired, - }; - render() { - return React.createElement('span', null, this.props.prop); - } - } - - const root = ReactDOMClient.createRoot(document.createElement('div')); - await expect(async () => { - await act(() => root.render(React.createElement(Component))); - await act(() => root.render(React.createElement(Component, {prop: 42}))); - }).toErrorDev([ - 'Warning: Failed prop type: ' + - 'The prop `prop` is marked as required in `Component`, but its value ' + - 'is `undefined`.\n' + - ' in Component', - 'Warning: Failed prop type: ' + - 'Invalid prop `prop` of type `number` supplied to ' + - '`Component`, expected `string`.\n' + - ' in Component', - ]); - - // Should not error for strings - await act(() => - root.render(React.createElement(Component, {prop: 'string'})), - ); - }); - - it('should warn if a PropType creator is used as a PropType', async () => { - class Component extends React.Component { - static propTypes = { - myProp: PropTypes.shape, - }; - render() { - return React.createElement('span', null, this.props.myProp.value); - } - } - - await expect(async () => { - const root = ReactDOMClient.createRoot(document.createElement('div')); - await act(() => - root.render(React.createElement(Component, {myProp: {value: 'hi'}})), - ); - }).toErrorDev( - 'Warning: Component: type specification of prop `myProp` is invalid; ' + - 'the type checker function must return `null` or an `Error` but ' + - 'returned a function. You may have forgotten to pass an argument to ' + - 'the type checker creator (arrayOf, instanceOf, objectOf, oneOf, ' + - 'oneOfType, and shape all require an argument).', - ); - }); - - it('should warn if component declares PropTypes instead of propTypes', async () => { - class MisspelledPropTypesComponent extends React.Component { - static PropTypes = { - prop: PropTypes.string, - }; - render() { - return React.createElement('span', null, this.props.prop); - } - } - - await expect(async () => { - const root = ReactDOMClient.createRoot(document.createElement('div')); - await act(() => - root.render( - React.createElement(MisspelledPropTypesComponent, {prop: 'Hi'}), - ), - ); - }).toErrorDev( - 'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' + - 'instead of `propTypes`. Did you misspell the property assignment?', - {withoutStack: true}, - ); - }); - it('warns for fragments with illegal attributes', async () => { class Foo extends React.Component { render() { diff --git a/packages/react/src/__tests__/ReactJSXElementValidator-test.js b/packages/react/src/__tests__/ReactJSXElementValidator-test.js index 3b2a9fd83bd1d..4a1a864be92e1 100644 --- a/packages/react/src/__tests__/ReactJSXElementValidator-test.js +++ b/packages/react/src/__tests__/ReactJSXElementValidator-test.js @@ -12,8 +12,6 @@ // TODO: All these warnings should become static errors using Flow instead // of dynamic errors when using JSX with Flow. let React; -let ReactDOM; -let ReactDOMClient; let ReactTestUtils; let PropTypes; let act; @@ -25,8 +23,6 @@ describe('ReactJSXElementValidator', () => { beforeEach(() => { PropTypes = require('prop-types'); React = require('react'); - ReactDOM = require('react-dom'); - ReactDOMClient = require('react-dom/client'); ReactTestUtils = require('react-dom/test-utils'); act = require('internal-test-utils').act; @@ -148,70 +144,6 @@ describe('ReactJSXElementValidator', () => { void ({[{}, {}]}); }); - it('should give context for PropType errors in nested components.', () => { - // In this test, we're making sure that if a proptype error is found in a - // component, we give a small hint as to which parent instantiated that - // component as per warnings about key usage in ReactElementValidator. - class MyComp extends React.Component { - render() { - return
My color is {this.color}
; - } - } - MyComp.propTypes = { - color: PropTypes.string, - }; - class ParentComp extends React.Component { - render() { - return ; - } - } - expect(() => ReactTestUtils.renderIntoDocument()).toErrorDev( - 'Warning: Failed prop type: ' + - 'Invalid prop `color` of type `number` supplied to `MyComp`, ' + - 'expected `string`.\n' + - ' in MyComp (at **)\n' + - ' in ParentComp (at **)', - ); - }); - - it('should update component stack after receiving next element', async () => { - function MyComp() { - return null; - } - MyComp.propTypes = { - color: PropTypes.string, - }; - function MiddleComp(props) { - return ; - } - function ParentComp(props) { - if (props.warn) { - // This element has a source thanks to JSX. - return ; - } - // This element has no source. - return React.createElement(MiddleComp, {color: 'blue'}); - } - - const container = document.createElement('div'); - const root = ReactDOMClient.createRoot(container); - await act(() => { - root.render(); - }); - expect(() => - ReactDOM.flushSync(() => { - root.render(); - }), - ).toErrorDev( - 'Warning: Failed prop type: ' + - 'Invalid prop `color` of type `number` supplied to `MyComp`, ' + - 'expected `string`.\n' + - ' in MyComp (at **)\n' + - ' in MiddleComp (at **)\n' + - ' in ParentComp (at **)', - ); - }); - it('gives a helpful error when passing null, undefined, or boolean', () => { const Undefined = undefined; const Null = null; @@ -244,71 +176,6 @@ describe('ReactJSXElementValidator', () => { void (
); }); - it('should check default prop values', () => { - RequiredPropComponent.defaultProps = {prop: null}; - - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `prop` is marked as required in ' + - '`RequiredPropComponent`, but its value is `null`.\n' + - ' in RequiredPropComponent (at **)', - ); - }); - - it('should not check the default for explicit null', () => { - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `prop` is marked as required in ' + - '`RequiredPropComponent`, but its value is `null`.\n' + - ' in RequiredPropComponent (at **)', - ); - }); - - it('should check declared prop types', () => { - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'Warning: Failed prop type: ' + - 'The prop `prop` is marked as required in `RequiredPropComponent`, but ' + - 'its value is `undefined`.\n' + - ' in RequiredPropComponent (at **)', - ); - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'Warning: Failed prop type: ' + - 'Invalid prop `prop` of type `number` supplied to ' + - '`RequiredPropComponent`, expected `string`.\n' + - ' in RequiredPropComponent (at **)', - ); - - // Should not error for strings - ReactTestUtils.renderIntoDocument(); - }); - - it('should warn on invalid prop types', () => { - // Since there is no prevalidation step for ES6 classes, there is no hook - // for us to issue a warning earlier than element creation when the error - // actually occurs. Since this step is skipped in production, we should just - // warn instead of throwing for this case. - class NullPropTypeComponent extends React.Component { - render() { - return {this.props.prop}; - } - } - NullPropTypeComponent.propTypes = { - prop: null, - }; - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'NullPropTypeComponent: prop type `prop` is invalid; it must be a ' + - 'function, usually from the `prop-types` package,', - ); - }); - // @gate !disableLegacyContext || !__DEV__ it('should warn on invalid context types', () => { class NullContextTypeComponent extends React.Component { @@ -327,44 +194,6 @@ describe('ReactJSXElementValidator', () => { ); }); - it('should warn if getDefaultProps is specified on the class', () => { - class GetDefaultPropsComponent extends React.Component { - render() { - return {this.props.prop}; - } - } - GetDefaultPropsComponent.getDefaultProps = () => ({ - prop: 'foo', - }); - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'getDefaultProps is only used on classic React.createClass definitions.' + - ' Use a static property named `defaultProps` instead.', - {withoutStack: true}, - ); - }); - - it('should warn if component declares PropTypes instead of propTypes', () => { - class MisspelledPropTypesComponent extends React.Component { - render() { - return {this.props.prop}; - } - } - MisspelledPropTypesComponent.PropTypes = { - prop: PropTypes.string, - }; - expect(() => - ReactTestUtils.renderIntoDocument( - , - ), - ).toErrorDev( - 'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' + - 'instead of `propTypes`. Did you misspell the property assignment?', - {withoutStack: true}, - ); - }); - it('warns for fragments with illegal attributes', () => { class Foo extends React.Component { render() { diff --git a/packages/react/src/__tests__/ReactTypeScriptClass-test.ts b/packages/react/src/__tests__/ReactTypeScriptClass-test.ts index 6f0dc668f5be7..86118b95e1e16 100644 --- a/packages/react/src/__tests__/ReactTypeScriptClass-test.ts +++ b/packages/react/src/__tests__/ReactTypeScriptClass-test.ts @@ -245,7 +245,6 @@ let getDefaultPropsWasCalled = false; class ClassicProperties extends React.Component { contextTypes = {}; contextType = {}; - propTypes = {}; getDefaultProps() { getDefaultPropsWasCalled = true; return {}; @@ -607,7 +606,6 @@ describe('ReactTypeScriptClass', function() { 'a plain JavaScript class.', 'getDefaultProps was defined on ClassicProperties, ' + 'a plain JavaScript class.', - 'propTypes was defined as an instance property on ClassicProperties.', 'contextTypes was defined as an instance property on ClassicProperties.', 'contextType was defined as an instance property on ClassicProperties.', ]); diff --git a/packages/react/src/jsx/ReactJSXElementValidator.js b/packages/react/src/jsx/ReactJSXElementValidator.js index 3fbbc1cdf2883..f15bf81e40aa6 100644 --- a/packages/react/src/jsx/ReactJSXElementValidator.js +++ b/packages/react/src/jsx/ReactJSXElementValidator.js @@ -13,11 +13,8 @@ */ import isValidElementType from 'shared/isValidElementType'; import getComponentNameFromType from 'shared/getComponentNameFromType'; -import checkPropTypes from 'shared/checkPropTypes'; import { getIteratorFn, - REACT_FORWARD_REF_TYPE, - REACT_MEMO_TYPE, REACT_FRAGMENT_TYPE, REACT_ELEMENT_TYPE, } from 'shared/ReactSymbols'; @@ -49,12 +46,6 @@ function setCurrentlyValidatingElement(element) { } } -let propTypesMisspellWarningShown; - -if (__DEV__) { - propTypesMisspellWarningShown = false; -} - /** * Verifies the object is a ReactElement. * See https://reactjs.org/docs/react-api.html#isvalidelement @@ -213,60 +204,6 @@ function validateChildKeys(node, parentType) { } } -/** - * Given an element, validate that its props follow the propTypes definition, - * provided by the type. - * - * @param {ReactElement} element - */ -function validatePropTypes(element) { - if (__DEV__) { - const type = element.type; - if (type === null || type === undefined || typeof type === 'string') { - return; - } - if (type.$$typeof === REACT_CLIENT_REFERENCE) { - return; - } - let propTypes; - if (typeof type === 'function') { - propTypes = type.propTypes; - } else if ( - typeof type === 'object' && - (type.$$typeof === REACT_FORWARD_REF_TYPE || - // Note: Memo only checks outer props here. - // Inner props are checked in the reconciler. - type.$$typeof === REACT_MEMO_TYPE) - ) { - propTypes = type.propTypes; - } else { - return; - } - if (propTypes) { - // Intentionally inside to avoid triggering lazy initializers: - const name = getComponentNameFromType(type); - checkPropTypes(propTypes, element.props, 'prop', name, element); - } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) { - propTypesMisspellWarningShown = true; - // Intentionally inside to avoid triggering lazy initializers: - const name = getComponentNameFromType(type); - console.error( - 'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', - name || 'Unknown', - ); - } - if ( - typeof type.getDefaultProps === 'function' && - !type.getDefaultProps.isReactClassApproved - ) { - console.error( - 'getDefaultProps is only used on classic React.createClass ' + - 'definitions. Use a static property named `defaultProps` instead.', - ); - } - } -} - /** * Given a fragment, validate that it can only be provided with fragment props * @param {ReactElement} fragment @@ -420,8 +357,6 @@ export function jsxWithValidation( if (type === REACT_FRAGMENT_TYPE) { validateFragmentProps(element); - } else { - validatePropTypes(element); } return element; diff --git a/packages/shared/checkPropTypes.js b/packages/shared/checkContextPropTypes.js similarity index 98% rename from packages/shared/checkPropTypes.js rename to packages/shared/checkContextPropTypes.js index 0b9582b236284..0d85220f09385 100644 --- a/packages/shared/checkPropTypes.js +++ b/packages/shared/checkContextPropTypes.js @@ -31,7 +31,7 @@ function setCurrentlyValidatingElement(element: any) { } } -export default function checkPropTypes( +export default function checkContextPropTypes( typeSpecs: Object, values: Object, location: string,