@samitouri / QOS-React / commits / fea900e454

Remove non-JSX propTypes checks (#28326)

Removes all `propTypes` validation called from outside the JSX factories. Haven't touched JSX. Tests that verify related behavior are stripped down to the non-`propTypes` logic.

dan committed Feb 16, 2024 at 00:35 UTC fea900e45447214ddd6ef69076ab7e38433b5ffd
6 files changed +56 -375
packages/react-reconciler/src/ReactFiberBeginWork.js
-135
@@ -40,7 +40,6 @@ import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent';
40 import type {TransitionStatus} from './ReactFiberConfig';
41 import type {Hook} from './ReactFiberHooks';
42
43 -import checkPropTypes from 'shared/checkPropTypes';
43 import {
44 markComponentRenderStarted,
45 markComponentRenderStopped,
@@ -401,23 +400,6 @@ function updateForwardRef(
400 // TODO: current can be non-null here even if the component
401 // hasn't yet mounted. This happens after the first render suspends.
402 // We'll need to figure out if this is fine or can cause issues.
404 -
405 - if (__DEV__) {
406 - if (workInProgress.type !== workInProgress.elementType) {
407 - // Lazy component props can't be validated in createElement
408 - // because they're only guaranteed to be resolved here.
409 - const innerPropTypes = Component.propTypes;
410 - if (innerPropTypes) {
411 - checkPropTypes(
412 - innerPropTypes,
413 - nextProps, // Resolved props
414 - 'prop',
415 - getComponentNameFromType(Component),
416 - );
417 - }
418 - }
419 - }
420 -
403 const render = Component.render;
404 const ref = workInProgress.ref;
405
@@ -507,17 +489,6 @@ function updateMemoComponent(
489 );
490 }
491 if (__DEV__) {
510 - const innerPropTypes = type.propTypes;
511 - if (innerPropTypes) {
512 - // Inner memo component props aren't currently validated in createElement.
513 - // We could move it there, but we'd still need this for lazy code path.
514 - checkPropTypes(
515 - innerPropTypes,
516 - nextProps, // Resolved props
517 - 'prop',
518 - getComponentNameFromType(type),
519 - );
520 - }
492 if (Component.defaultProps !== undefined) {
493 const componentName = getComponentNameFromType(type) || 'Unknown';
494 if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) {
@@ -543,20 +514,6 @@ function updateMemoComponent(
514 workInProgress.child = child;
515 return child;
516 }
546 - if (__DEV__) {
547 - const type = Component.type;
548 - const innerPropTypes = type.propTypes;
549 - if (innerPropTypes) {
550 - // Inner memo component props aren't currently validated in createElement.
551 - // We could move it there, but we'd still need this for lazy code path.
552 - checkPropTypes(
553 - innerPropTypes,
554 - nextProps, // Resolved props
555 - 'prop',
556 - getComponentNameFromType(type),
557 - );
558 - }
559 - }
517 const currentChild = ((current.child: any): Fiber); // This is always exactly one child
518 const hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(
519 current,
@@ -592,37 +549,6 @@ function updateSimpleMemoComponent(
549 // TODO: current can be non-null here even if the component
550 // hasn't yet mounted. This happens when the inner render suspends.
551 // We'll need to figure out if this is fine or can cause issues.
595 -
596 - if (__DEV__) {
597 - if (workInProgress.type !== workInProgress.elementType) {
598 - // Lazy component props can't be validated in createElement
599 - // because they're only guaranteed to be resolved here.
600 - let outerMemoType = workInProgress.elementType;
601 - if (outerMemoType.$$typeof === REACT_LAZY_TYPE) {
602 - // We warn when you define propTypes on lazy()
603 - // so let's just skip over it to find memo() outer wrapper.
604 - // Inner props for memo are validated later.
605 - const lazyComponent: LazyComponentType<any, any> = outerMemoType;
606 - const payload = lazyComponent._payload;
607 - const init = lazyComponent._init;
608 - try {
609 - outerMemoType = init(payload);
610 - } catch (x) {
611 - outerMemoType = null;
612 - }
613 - // Inner propTypes will be validated in the function component path.
614 - const outerPropTypes = outerMemoType && (outerMemoType: any).propTypes;
615 - if (outerPropTypes) {
616 - checkPropTypes(
617 - outerPropTypes,
618 - nextProps, // Resolved (SimpleMemoComponent has no defaultProps)
619 - 'prop',
620 - getComponentNameFromType(outerMemoType),
621 - );
622 - }
623 - }
624 - }
625 - }
552 if (current !== null) {
553 const prevProps = current.memoizedProps;
554 if (
@@ -1099,22 +1025,6 @@ function updateFunctionComponent(
1025 nextProps: any,
1026 renderLanes: Lanes,
1027 ) {
1102 - if (__DEV__) {
1103 - if (workInProgress.type !== workInProgress.elementType) {
1104 - // Lazy component props can't be validated in createElement
1105 - // because they're only guaranteed to be resolved here.
1106 - const innerPropTypes = Component.propTypes;
1107 - if (innerPropTypes) {
1108 - checkPropTypes(
1109 - innerPropTypes,
1110 - nextProps, // Resolved props
1111 - 'prop',
1112 - getComponentNameFromType(Component),
1113 - );
1114 - }
1115 - }
1116 - }
1117 -
1028 let context;
1029 if (!disableLegacyContext) {
1030 const unmaskedContext = getUnmaskedContext(workInProgress, Component, true);
@@ -1253,20 +1163,6 @@ function updateClassComponent(
1163 break;
1164 }
1165 }
1256 -
1257 - if (workInProgress.type !== workInProgress.elementType) {
1258 - // Lazy component props can't be validated in createElement
1259 - // because they're only guaranteed to be resolved here.
1260 - const innerPropTypes = Component.propTypes;
1261 - if (innerPropTypes) {
1262 - checkPropTypes(
1263 - innerPropTypes,
1264 - nextProps, // Resolved props
1265 - 'prop',
1266 - getComponentNameFromType(Component),
1267 - );
1268 - }
1269 - }
1166 }
1167
1168 // Push context providers early to prevent context stack mismatches.
@@ -1815,19 +1711,6 @@ function mountLazyComponent(
1711 return child;
1712 }
1713 case MemoComponent: {
1818 - if (__DEV__) {
1819 - if (workInProgress.type !== workInProgress.elementType) {
1820 - const outerPropTypes = Component.propTypes;
1821 - if (outerPropTypes) {
1822 - checkPropTypes(
1823 - outerPropTypes,
1824 - resolvedProps, // Resolved for outer only
1825 - 'prop',
1826 - getComponentNameFromType(Component),
1827 - );
1828 - }
1829 - }
1830 - }
1714 child = updateMemoComponent(
1715 null,
1716 workInProgress,
@@ -3549,11 +3432,6 @@ function updateContextProvider(
3432 );
3433 }
3434 }
3552 - const providerPropTypes = workInProgress.type.propTypes;
3553 -
3554 - if (providerPropTypes) {
3555 - checkPropTypes(providerPropTypes, newProps, 'prop', 'Context.Provider');
3556 - }
3435 }
3436
3437 pushProvider(workInProgress, context, newValue);
@@ -4229,19 +4107,6 @@ function beginWork(
4107 const unresolvedProps = workInProgress.pendingProps;
4108 // Resolve outer props first, then resolve inner props.
4109 let resolvedProps = resolveDefaultProps(type, unresolvedProps);
4232 - if (__DEV__) {
4233 - if (workInProgress.type !== workInProgress.elementType) {
4234 - const outerPropTypes = type.propTypes;
4235 - if (outerPropTypes) {
4236 - checkPropTypes(
4237 - outerPropTypes,
4238 - resolvedProps, // Resolved for outer only
4239 - 'prop',
4240 - getComponentNameFromType(type),
4241 - );
4242 - }
4243 - }
4244 - }
4110 resolvedProps = resolveDefaultProps(type.type, resolvedProps);
4111 return updateMemoComponent(
4112 current,
packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js
+33 -111
@@ -1,4 +1,3 @@
1 -let PropTypes;
1 let React;
2 let ReactTestRenderer;
3 let Scheduler;
@@ -28,7 +27,6 @@ describe('ReactLazy', () => {
27 ReactFeatureFlags = require('shared/ReactFeatureFlags');
28
29 ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
31 - PropTypes = require('prop-types');
30 React = require('react');
31 Suspense = React.Suspense;
32 lazy = React.lazy;
@@ -783,33 +781,12 @@ describe('ReactLazy', () => {
781 );
782 });
783
786 - it('warns about defining propTypes on the outer wrapper', () => {
787 - const LazyText = lazy(() => fakeImport(Text));
788 - expect(() => {
789 - LazyText.propTypes = {hello: () => {}};
790 - }).toErrorDev(
791 - 'React.lazy(...): It is not supported to assign `propTypes` to ' +
792 - 'a lazy component import. Either specify them where the component ' +
793 - 'is defined, or create a wrapping component around it.',
794 - {withoutStack: true},
795 - );
796 - });
797 -
798 - async function verifyInnerPropTypesAreChecked(
784 + async function verifyResolvesProps(
785 Add,
786 shouldWarnAboutFunctionDefaultProps,
787 shouldWarnAboutMemoDefaultProps,
788 ) {
789 const LazyAdd = lazy(() => fakeImport(Add));
804 - expect(() => {
805 - LazyAdd.propTypes = {};
806 - }).toErrorDev(
807 - 'React.lazy(...): It is not supported to assign `propTypes` to ' +
808 - 'a lazy component import. Either specify them where the component ' +
809 - 'is defined, or create a wrapping component around it.',
810 - {withoutStack: true},
811 - );
812 -
790 const root = ReactTestRenderer.create(
791 <Suspense fallback={<Text text="Loading..." />}>
792 <LazyAdd inner="2" outer="2" />
@@ -820,7 +797,6 @@ describe('ReactLazy', () => {
797 );
798
799 await waitForAll(['Loading...']);
823 -
800 expect(root).not.toMatchRenderedOutput('22');
801
802 // Mount
@@ -830,171 +806,126 @@ describe('ReactLazy', () => {
806 shouldWarnAboutFunctionDefaultProps
807 ? [
808 'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.',
833 - 'Invalid prop `inner` of type `string` supplied to `Add`, expected `number`.',
809 ]
810 : shouldWarnAboutMemoDefaultProps
811 ? [
812 'Add: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.',
838 - 'Invalid prop `inner` of type `string` supplied to `Add`, expected `number`.',
813 ]
840 - : [
841 - 'Invalid prop `inner` of type `string` supplied to `Add`, expected `number`.',
842 - ],
814 + : [],
815 );
816 expect(root).toMatchRenderedOutput('22');
817
818 // Update
847 - await expect(async () => {
848 - root.update(
849 - <Suspense fallback={<Text text="Loading..." />}>
850 - <LazyAdd inner={false} outer={false} />
851 - </Suspense>,
852 - );
853 - await waitForAll([]);
854 - }).toErrorDev(
855 - 'Invalid prop `inner` of type `boolean` supplied to `Add`, expected `number`.',
819 + root.update(
820 + <Suspense fallback={<Text text="Loading..." />}>
821 + <LazyAdd inner={false} outer={false} />
822 + </Suspense>,
823 );
824 + await waitForAll([]);
825 expect(root).toMatchRenderedOutput('0');
826 }
827
860 - // Note: all "with defaultProps" tests below also verify defaultProps works as expected.
861 - // If we ever delete or move propTypes-related tests, make sure not to delete these.
862 - it('respects propTypes on function component with defaultProps', async () => {
828 + it('resolves props for function component with defaultProps', async () => {
829 function Add(props) {
830 expect(props.innerWithDefault).toBe(42);
831 return props.inner + props.outer;
832 }
867 - Add.propTypes = {
868 - inner: PropTypes.number.isRequired,
869 - innerWithDefault: PropTypes.number.isRequired,
870 - };
833 Add.defaultProps = {
834 innerWithDefault: 42,
835 };
874 - await verifyInnerPropTypesAreChecked(Add, true);
836 + await verifyResolvesProps(Add, true);
837 });
838
877 - it('respects propTypes on function component without defaultProps', async () => {
839 + it('resolves props for function component without defaultProps', async () => {
840 function Add(props) {
841 return props.inner + props.outer;
842 }
881 - Add.propTypes = {
882 - inner: PropTypes.number.isRequired,
883 - };
884 - await verifyInnerPropTypesAreChecked(Add);
843 + await verifyResolvesProps(Add);
844 });
845
887 - it('respects propTypes on class component with defaultProps', async () => {
846 + it('resolves props for class component with defaultProps', async () => {
847 class Add extends React.Component {
848 render() {
849 expect(this.props.innerWithDefault).toBe(42);
850 return this.props.inner + this.props.outer;
851 }
852 }
894 - Add.propTypes = {
895 - inner: PropTypes.number.isRequired,
896 - innerWithDefault: PropTypes.number.isRequired,
897 - };
853 Add.defaultProps = {
854 innerWithDefault: 42,
855 };
901 - await verifyInnerPropTypesAreChecked(Add);
856 + await verifyResolvesProps(Add);
857 });
858
904 - it('respects propTypes on class component without defaultProps', async () => {
859 + it('resolves props for class component without defaultProps', async () => {
860 class Add extends React.Component {
861 render() {
862 return this.props.inner + this.props.outer;
863 }
864 }
910 - Add.propTypes = {
911 - inner: PropTypes.number.isRequired,
912 - };
913 - await verifyInnerPropTypesAreChecked(Add);
865 + await verifyResolvesProps(Add);
866 });
867
916 - it('respects propTypes on forwardRef component with defaultProps', async () => {
868 + it('resolves props for forwardRef component with defaultProps', async () => {
869 const Add = React.forwardRef((props, ref) => {
870 expect(props.innerWithDefault).toBe(42);
871 return props.inner + props.outer;
872 });
873 Add.displayName = 'Add';
922 - Add.propTypes = {
923 - inner: PropTypes.number.isRequired,
924 - innerWithDefault: PropTypes.number.isRequired,
925 - };
874 Add.defaultProps = {
875 innerWithDefault: 42,
876 };
929 - await verifyInnerPropTypesAreChecked(Add);
877 + await verifyResolvesProps(Add);
878 });
879
932 - it('respects propTypes on forwardRef component without defaultProps', async () => {
880 + it('resolves props for forwardRef component without defaultProps', async () => {
881 const Add = React.forwardRef((props, ref) => {
882 return props.inner + props.outer;
883 });
884 Add.displayName = 'Add';
937 - Add.propTypes = {
938 - inner: PropTypes.number.isRequired,
939 - };
940 - await verifyInnerPropTypesAreChecked(Add);
885 + await verifyResolvesProps(Add);
886 });
887
943 - it('respects propTypes on outer memo component with defaultProps', async () => {
888 + it('resolves props for outer memo component with defaultProps', async () => {
889 let Add = props => {
890 expect(props.innerWithDefault).toBe(42);
891 return props.inner + props.outer;
892 };
893 Add = React.memo(Add);
949 - Add.propTypes = {
950 - inner: PropTypes.number.isRequired,
951 - innerWithDefault: PropTypes.number.isRequired,
952 - };
894 Add.defaultProps = {
895 innerWithDefault: 42,
896 };
956 - await verifyInnerPropTypesAreChecked(Add, false, true);
897 + await verifyResolvesProps(Add, false, true);
898 });
899
959 - it('respects propTypes on outer memo component without defaultProps', async () => {
900 + it('resolves props for outer memo component without defaultProps', async () => {
901 let Add = props => {
902 return props.inner + props.outer;
903 };
904 Add = React.memo(Add);
964 - Add.propTypes = {
965 - inner: PropTypes.number.isRequired,
966 - };
967 - await verifyInnerPropTypesAreChecked(Add);
905 + await verifyResolvesProps(Add);
906 });
907
970 - it('respects propTypes on inner memo component with defaultProps', async () => {
908 + it('resolves props for inner memo component with defaultProps', async () => {
909 const Add = props => {
910 expect(props.innerWithDefault).toBe(42);
911 return props.inner + props.outer;
912 };
913 Add.displayName = 'Add';
976 - Add.propTypes = {
977 - inner: PropTypes.number.isRequired,
978 - innerWithDefault: PropTypes.number.isRequired,
979 - };
914 Add.defaultProps = {
915 innerWithDefault: 42,
916 };
983 - await verifyInnerPropTypesAreChecked(React.memo(Add), true);
917 + await verifyResolvesProps(React.memo(Add), true);
918 });
919
986 - it('respects propTypes on inner memo component without defaultProps', async () => {
920 + it('resolves props for inner memo component without defaultProps', async () => {
921 const Add = props => {
922 return props.inner + props.outer;
923 };
924 Add.displayName = 'Add';
991 - Add.propTypes = {
992 - inner: PropTypes.number.isRequired,
993 - };
994 - await verifyInnerPropTypesAreChecked(React.memo(Add));
925 + await verifyResolvesProps(React.memo(Add));
926 });
927
997 - it('uses outer resolved props for validating propTypes on memo', async () => {
928 + it('uses outer resolved props on memo', async () => {
929 let T = props => {
930 return <Text text={props.text} />;
931 };
@@ -1002,10 +933,6 @@ describe('ReactLazy', () => {
933 text: 'Inner default text',
934 };
935 T = React.memo(T);
1005 - T.propTypes = {
1006 - // Should not be satisfied by the *inner* defaultProps.
1007 - text: PropTypes.string.isRequired,
1008 - };
936 const LazyText = lazy(() => fakeImport(T));
937 const root = ReactTestRenderer.create(
938 <Suspense fallback={<Text text="Loading..." />}>
@@ -1025,21 +952,16 @@ describe('ReactLazy', () => {
952 assertLog(['Inner default text']);
953 }).toErrorDev([
954 'T: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.',
1028 - 'The prop `text` is marked as required in `T`, but its value is `undefined`',
955 ]);
956 expect(root).toMatchRenderedOutput('Inner default text');
957
958 // Update
1033 - await expect(async () => {
1034 - root.update(
1035 - <Suspense fallback={<Text text="Loading..." />}>
1036 - <LazyText text={null} />
1037 - </Suspense>,
1038 - );
1039 - await waitForAll([null]);
1040 - }).toErrorDev(
1041 - 'The prop `text` is marked as required in `T`, but its value is `null`',
959 + root.update(
960 + <Suspense fallback={<Text text="Loading..." />}>
961 + <LazyText text={null} />
962 + </Suspense>,
963 );
964 + await waitForAll([null]);
965 expect(root).toMatchRenderedOutput(null);
966 });
967
packages/react-reconciler/src/__tests__/ReactMemo-test.js
+18 -89
@@ -12,7 +12,6 @@
12
13 'use strict';
14
15 -let PropTypes;
15 let React;
16 let ReactNoop;
17 let Suspense;
@@ -25,7 +24,6 @@ describe('memo', () => {
24 beforeEach(() => {
25 jest.resetModules();
26
28 - PropTypes = require('prop-types');
27 React = require('react');
28 ReactNoop = require('react-noop-renderer');
29 Scheduler = require('scheduler');
@@ -483,108 +481,39 @@ describe('memo', () => {
481 );
482 });
483
486 - it('validates propTypes declared on the inner component', async () => {
487 - function FnInner(props) {
488 - return props.inner;
489 - }
490 - FnInner.propTypes = {inner: PropTypes.number.isRequired};
491 - const Fn = React.memo(FnInner);
492 -
493 - // Mount
494 - await expect(async () => {
495 - ReactNoop.render(<Fn inner="2" />);
496 - await waitForAll([]);
497 - }).toErrorDev(
498 - 'Invalid prop `inner` of type `string` supplied to `FnInner`, expected `number`.',
499 - );
500 -
501 - // Update
502 - await expect(async () => {
503 - ReactNoop.render(<Fn inner={false} />);
504 - await waitForAll([]);
505 - }).toErrorDev(
506 - 'Invalid prop `inner` of type `boolean` supplied to `FnInner`, expected `number`.',
507 - );
508 - });
509 -
510 - it('validates propTypes declared on the outer component', async () => {
511 - function FnInner(props) {
512 - return props.outer;
513 - }
514 - const Fn = React.memo(FnInner);
515 - Fn.propTypes = {outer: PropTypes.number.isRequired};
516 -
517 - // Mount
518 - await expect(async () => {
519 - ReactNoop.render(<Fn outer="3" />);
520 - await waitForAll([]);
521 - }).toErrorDev(
522 - // Outer props are checked in createElement
523 - 'Invalid prop `outer` of type `string` supplied to `FnInner`, expected `number`.',
524 - );
525 -
526 - // Update
527 - await expect(async () => {
528 - ReactNoop.render(<Fn outer={false} />);
529 - await waitForAll([]);
530 - }).toErrorDev(
531 - // Outer props are checked in createElement
532 - 'Invalid prop `outer` of type `boolean` supplied to `FnInner`, expected `number`.',
533 - );
534 - });
535 -
536 - it('validates nested propTypes declarations', async () => {
484 + it('handles nested defaultProps declarations', async () => {
485 function Inner(props) {
486 return props.inner + props.middle + props.outer;
487 }
540 - Inner.propTypes = {inner: PropTypes.number.isRequired};
541 - Inner.defaultProps = {inner: 0};
488 + Inner.defaultProps = {inner: 1};
489 const Middle = React.memo(Inner);
543 - Middle.propTypes = {middle: PropTypes.number.isRequired};
544 - Middle.defaultProps = {middle: 0};
490 + Middle.defaultProps = {middle: 10};
491 const Outer = React.memo(Middle);
546 - Outer.propTypes = {outer: PropTypes.number.isRequired};
547 - Outer.defaultProps = {outer: 0};
492 + Outer.defaultProps = {outer: 100};
493
549 - // No warning expected because defaultProps satisfy both.
550 - ReactNoop.render(
551 - <div>
552 - <Outer />
553 - </div>,
554 - );
494 + const root = ReactNoop.createRoot();
495 await expect(async () => {
556 - await waitForAll([]);
496 + await act(() => {
497 + root.render(
498 + <div>
499 + <Outer />
500 + </div>,
501 + );
502 + });
503 }).toErrorDev([
558 - 'Inner: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.',
504 + 'Support for defaultProps will be removed from memo component',
505 ]);
506 + expect(root).toMatchRenderedOutput(<div>111</div>);
507
561 - // Mount
562 - await expect(async () => {
563 - ReactNoop.render(
508 + await act(async () => {
509 + root.render(
510 <div>
511 <Outer inner="2" middle="3" outer="4" />
512 </div>,
513 );
514 await waitForAll([]);
569 - }).toErrorDev([
570 - 'Invalid prop `outer` of type `string` supplied to `Inner`, expected `number`.',
571 - 'Invalid prop `middle` of type `string` supplied to `Inner`, expected `number`.',
572 - 'Invalid prop `inner` of type `string` supplied to `Inner`, expected `number`.',
573 - ]);
574 -
575 - // Update
576 - await expect(async () => {
577 - ReactNoop.render(
578 - <div>
579 - <Outer inner={false} middle={false} outer={false} />
580 - </div>,
581 - );
582 - await waitForAll([]);
583 - }).toErrorDev([
584 - 'Invalid prop `outer` of type `boolean` supplied to `Inner`, expected `number`.',
585 - 'Invalid prop `middle` of type `boolean` supplied to `Inner`, expected `number`.',
586 - 'Invalid prop `inner` of type `boolean` supplied to `Inner`, expected `number`.',
587 - ]);
515 + });
516 + expect(root).toMatchRenderedOutput(<div>234</div>);
517 });
518
519 it('does not drop lower priority state updates when bailing out at higher pri (simple)', async () => {
packages/react-server/src/ReactFizzContext.js
-11
@@ -9,7 +9,6 @@
9
10 import {disableLegacyContext} from 'shared/ReactFeatureFlags';
11 import getComponentNameFromType from 'shared/getComponentNameFromType';
12 -import checkPropTypes from 'shared/checkPropTypes';
12
13 let warnedAboutMissingGetChildContext;
14
@@ -36,11 +35,6 @@ export function getMaskedContext(type: any, unmaskedContext: Object): Object {
35 context[key] = unmaskedContext[key];
36 }
37
39 - if (__DEV__) {
40 - const name = getComponentNameFromType(type) || 'Unknown';
41 - checkPropTypes(contextTypes, context, 'context', name);
42 - }
43 -
38 return context;
39 }
40 }
@@ -84,11 +78,6 @@ export function processChildContext(
78 );
79 }
80 }
87 - if (__DEV__) {
88 - const name = getComponentNameFromType(type) || 'Unknown';
89 - checkPropTypes(childContextTypes, childContext, 'child context', name);
90 - }
91 -
81 return {...parentContext, ...childContext};
82 }
83 }
packages/react/src/ReactForwardRef.js
+2 -2
@@ -36,9 +36,9 @@ export function forwardRef<Props, ElementType: React$ElementType>(
36 }
37
38 if (render != null) {
39 - if (render.defaultProps != null || render.propTypes != null) {
39 + if (render.defaultProps != null) {
40 console.error(
41 - 'forwardRef render functions do not support propTypes or defaultProps. ' +
41 + 'forwardRef render functions do not support defaultProps. ' +
42 'Did you accidentally pass a React component?',
43 );
44 }
packages/react/src/__tests__/forwardRef-test.js
+3 -27
@@ -10,14 +10,12 @@
10 'use strict';
11
12 describe('forwardRef', () => {
13 - let PropTypes;
13 let React;
14 let ReactNoop;
15 let waitForAll;
16
17 beforeEach(() => {
18 jest.resetModules();
20 - PropTypes = require('prop-types');
19 React = require('react');
20 ReactNoop = require('react-noop-renderer');
21
@@ -76,7 +74,7 @@ describe('forwardRef', () => {
74 expect(ref.current).toBe(null);
75 });
76
79 - it('should support propTypes and defaultProps', async () => {
77 + it('should support defaultProps', async () => {
78 function FunctionComponent({forwardedRef, optional, required}) {
79 return (
80 <div ref={forwardedRef}>
@@ -91,10 +89,6 @@ describe('forwardRef', () => {
89 return <FunctionComponent {...props} forwardedRef={ref} />;
90 },
91 );
94 - RefForwardingComponent.propTypes = {
95 - optional: PropTypes.string,
96 - required: PropTypes.string.isRequired,
97 - };
92 RefForwardingComponent.defaultProps = {
93 optional: 'default',
94 };
@@ -116,14 +110,6 @@ describe('forwardRef', () => {
110 {text: 'default', hidden: false},
111 {text: 'foo', hidden: false},
112 ]);
119 -
120 - expect(() =>
121 - ReactNoop.render(<RefForwardingComponent ref={ref} optional="foo" />),
122 - ).toErrorDev(
123 - 'Warning: Failed prop type: The prop `required` is marked as required in ' +
124 - '`ForwardRef(NamedFunction)`, but its value is `undefined`.\n' +
125 - ' in NamedFunction (at **)',
126 - );
113 });
114
115 it('should warn if not provided a callback during creation', () => {
@@ -150,24 +136,14 @@ describe('forwardRef', () => {
136 );
137 });
138
153 - it('should warn if the render function provided has propTypes or defaultProps attributes', () => {
154 - function renderWithPropTypes(props, ref) {
155 - return null;
156 - }
157 - renderWithPropTypes.propTypes = {};
158 -
139 + it('should warn if the render function provided has defaultProps attributes', () => {
140 function renderWithDefaultProps(props, ref) {
141 return null;
142 }
143 renderWithDefaultProps.defaultProps = {};
144
164 - expect(() => React.forwardRef(renderWithPropTypes)).toErrorDev(
165 - 'forwardRef render functions do not support propTypes or defaultProps. ' +
166 - 'Did you accidentally pass a React component?',
167 - {withoutStack: true},
168 - );
145 expect(() => React.forwardRef(renderWithDefaultProps)).toErrorDev(
170 - 'forwardRef render functions do not support propTypes or defaultProps. ' +
146 + 'forwardRef render functions do not support defaultProps. ' +
147 'Did you accidentally pass a React component?',
148 {withoutStack: true},
149 );