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
);