Skip to content

Commit 353ecd0

Browse files
authored
Remove JSX propTypes validation (#28328)
This removes the remaining `propTypes` validation calls, making declaring `propTypes` a no-op. In other words, React itself will no longer validate the `propTypes` that you declare on your components. In general, our recommendation is to use static type checking (e.g. TypeScript). If you'd like to still run propTypes checks, you can do so manually, same as you'd do outside React: ```js import checkPropTypes from 'prop-types/checkPropTypes'; function Button(props) { checkPropTypes(Button.propTypes, prop, 'prop', Button.name) // ... } ``` This could be automated as a Babel plugin if you want to keep these checks implicit. (We will not be providing such a plugin, but someone in community might be interested in building or maintaining one.)
1 parent 4ea424e commit 353ecd0

10 files changed

+12
-588
lines changed

packages/react-art/npm/Circle.js

-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
'use strict';
1919

2020
var assign = Object.assign;
21-
var PropTypes = require('prop-types');
2221
var React = require('react');
2322
var ReactART = require('react-art');
2423

@@ -34,10 +33,6 @@ var Shape = ReactART.Shape;
3433
var Circle = createReactClass({
3534
displayName: 'Circle',
3635

37-
propTypes: {
38-
radius: PropTypes.number.isRequired,
39-
},
40-
4136
render: function render() {
4237
var radius = this.props.radius;
4338

packages/react-art/npm/Rectangle.js

-11
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
'use strict';
2626

2727
var assign = Object.assign;
28-
var PropTypes = require('prop-types');
2928
var React = require('react');
3029
var ReactART = require('react-art');
3130

@@ -41,16 +40,6 @@ var Path = ReactART.Path;
4140
var Rectangle = createReactClass({
4241
displayName: 'Rectangle',
4342

44-
propTypes: {
45-
width: PropTypes.number.isRequired,
46-
height: PropTypes.number.isRequired,
47-
radius: PropTypes.number,
48-
radiusTopLeft: PropTypes.number,
49-
radiusTopRight: PropTypes.number,
50-
radiusBottomRight: PropTypes.number,
51-
radiusBottomLeft: PropTypes.number,
52-
},
53-
5443
render: function render() {
5544
var width = this.props.width;
5645
var height = this.props.height;

packages/react-art/npm/Wedge.js

-8
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
'use strict';
2222

2323
var assign = Object.assign;
24-
var PropTypes = require('prop-types');
2524
var React = require('react');
2625
var ReactART = require('react-art');
2726

@@ -37,13 +36,6 @@ var Path = ReactART.Path;
3736
var Wedge = createReactClass({
3837
displayName: 'Wedge',
3938

40-
propTypes: {
41-
outerRadius: PropTypes.number.isRequired,
42-
startAngle: PropTypes.number.isRequired,
43-
endAngle: PropTypes.number.isRequired,
44-
innerRadius: PropTypes.number,
45-
},
46-
4739
circleRadians: Math.PI * 2,
4840

4941
radiansPerDegree: Math.PI / 180,

packages/react-art/src/__tests__/ReactART-test.js

-39
Original file line numberDiff line numberDiff line change
@@ -456,18 +456,6 @@ describe('ReactARTComponents', () => {
456456
expect(circle.toJSON()).toMatchSnapshot();
457457
});
458458

459-
it('should warn if radius is missing on a Circle component', () => {
460-
expect(() =>
461-
ReactTestRenderer.create(
462-
<Circle stroke="green" strokeWidth={3} fill="blue" />,
463-
),
464-
).toErrorDev(
465-
'Warning: Failed prop type: The prop `radius` is marked as required in `Circle`, ' +
466-
'but its value is `undefined`.' +
467-
'\n in Circle (at **)',
468-
);
469-
});
470-
471459
it('should generate a <Shape> with props for drawing the Rectangle', () => {
472460
const rectangle = ReactTestRenderer.create(
473461
<Rectangle width={50} height={50} stroke="green" fill="blue" />,
@@ -529,19 +517,6 @@ describe('ReactARTComponents', () => {
529517
expect(rectangle.toJSON()).toMatchSnapshot();
530518
});
531519

532-
it('should warn if width/height is missing on a Rectangle component', () => {
533-
expect(() =>
534-
ReactTestRenderer.create(<Rectangle stroke="green" fill="blue" />),
535-
).toErrorDev([
536-
'Warning: Failed prop type: The prop `width` is marked as required in `Rectangle`, ' +
537-
'but its value is `undefined`.' +
538-
'\n in Rectangle (at **)',
539-
'Warning: Failed prop type: The prop `height` is marked as required in `Rectangle`, ' +
540-
'but its value is `undefined`.' +
541-
'\n in Rectangle (at **)',
542-
]);
543-
});
544-
545520
it('should generate a <Shape> with props for drawing the Wedge', () => {
546521
const wedge = ReactTestRenderer.create(
547522
<Wedge outerRadius={50} startAngle={0} endAngle={360} fill="blue" />,
@@ -555,18 +530,4 @@ describe('ReactARTComponents', () => {
555530
);
556531
expect(wedge.toJSON()).toBeNull();
557532
});
558-
559-
it('should warn if outerRadius/startAngle/endAngle is missing on a Wedge component', () => {
560-
expect(() => ReactTestRenderer.create(<Wedge fill="blue" />)).toErrorDev([
561-
'Warning: Failed prop type: The prop `outerRadius` is marked as required in `Wedge`, ' +
562-
'but its value is `undefined`.' +
563-
'\n in Wedge (at **)',
564-
'Warning: Failed prop type: The prop `startAngle` is marked as required in `Wedge`, ' +
565-
'but its value is `undefined`.' +
566-
'\n in Wedge (at **)',
567-
'Warning: Failed prop type: The prop `endAngle` is marked as required in `Wedge`, ' +
568-
'but its value is `undefined`.' +
569-
'\n in Wedge (at **)',
570-
]);
571-
});
572533
});

packages/react-dom/src/__tests__/ReactFunctionComponent-test.js

+1-7
Original file line numberDiff line numberDiff line change
@@ -433,14 +433,11 @@ describe('ReactFunctionComponent', () => {
433433
);
434434
});
435435

436-
// TODO: change this test after we deprecate default props support
437-
// for function components
438-
it('should support default props and prop types', async () => {
436+
it('should support default props', async () => {
439437
function Child(props) {
440438
return <div>{props.test}</div>;
441439
}
442440
Child.defaultProps = {test: 2};
443-
Child.propTypes = {test: PropTypes.string};
444441

445442
await expect(async () => {
446443
const container = document.createElement('div');
@@ -451,9 +448,6 @@ describe('ReactFunctionComponent', () => {
451448
});
452449
}).toErrorDev([
453450
'Warning: Child: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.',
454-
'Warning: Failed prop type: Invalid prop `test` of type `number` ' +
455-
'supplied to `Child`, expected `string`.\n' +
456-
' in Child (at **)',
457451
]);
458452
});
459453

packages/react/src/__tests__/ReactElementClone-test.js

-37
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
'use strict';
1111

1212
let act;
13-
let PropTypes;
1413
let React;
1514
let ReactDOMClient;
1615

@@ -22,7 +21,6 @@ describe('ReactElementClone', () => {
2221

2322
act = require('internal-test-utils').act;
2423

25-
PropTypes = require('prop-types');
2624
React = require('react');
2725
ReactDOMClient = require('react-dom/client');
2826

@@ -335,41 +333,6 @@ describe('ReactElementClone', () => {
335333
React.cloneElement(<div />, null, [{}, {}]);
336334
});
337335

338-
it('should check declared prop types after clone', async () => {
339-
class Component extends React.Component {
340-
static propTypes = {
341-
color: PropTypes.string.isRequired,
342-
};
343-
render() {
344-
return React.createElement('div', null, 'My color is ' + this.color);
345-
}
346-
}
347-
class Parent extends React.Component {
348-
render() {
349-
return React.cloneElement(this.props.child, {color: 123});
350-
}
351-
}
352-
class GrandParent extends React.Component {
353-
render() {
354-
return React.createElement(Parent, {
355-
child: React.createElement(Component, {color: 'red'}),
356-
});
357-
}
358-
}
359-
const root = ReactDOMClient.createRoot(document.createElement('div'));
360-
await expect(
361-
async () =>
362-
await act(() => root.render(React.createElement(GrandParent))),
363-
).toErrorDev(
364-
'Warning: Failed prop type: ' +
365-
'Invalid prop `color` of type `number` supplied to `Component`, ' +
366-
'expected `string`.\n' +
367-
' in Component (at **)\n' +
368-
' in Parent (at **)\n' +
369-
' in GrandParent',
370-
);
371-
});
372-
373336
it('should ignore key and ref warning getters', () => {
374337
const elementA = React.createElement('div');
375338
const elementB = React.cloneElement(elementA, elementA.props);

packages/react/src/__tests__/ReactElementValidator-test.internal.js

+6-134
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
// that do use JSX syntax. We should port them to React.createElement, and also
1616
// confirm there's a corresponding test that uses JSX syntax.
1717

18-
let PropTypes;
1918
let React;
2019
let ReactDOMClient;
2120
let act;
@@ -28,7 +27,6 @@ describe('ReactElementValidator', () => {
2827
beforeEach(() => {
2928
jest.resetModules();
3029

31-
PropTypes = require('prop-types');
3230
ReactFeatureFlags = require('shared/ReactFeatureFlags');
3331
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
3432
React = require('react');
@@ -221,26 +219,19 @@ describe('ReactElementValidator', () => {
221219
React.createElement(ComponentClass, null, [{}, {}]);
222220
});
223221

224-
it('should give context for PropType errors in nested components.', async () => {
225-
// In this test, we're making sure that if a proptype error is found in a
226-
// component, we give a small hint as to which parent instantiated that
227-
// component as per warnings about key usage in ReactElementValidator.
228-
function MyComp(props) {
229-
return React.createElement('div', null, 'My color is ' + props.color);
222+
it('should give context for errors in nested components.', async () => {
223+
function MyComp() {
224+
return [React.createElement('div')];
230225
}
231-
MyComp.propTypes = {
232-
color: PropTypes.string,
233-
};
234226
function ParentComp() {
235-
return React.createElement(MyComp, {color: 123});
227+
return React.createElement(MyComp);
236228
}
237229
await expect(async () => {
238230
const root = ReactDOMClient.createRoot(document.createElement('div'));
239231
await act(() => root.render(React.createElement(ParentComp)));
240232
}).toErrorDev(
241-
'Warning: Failed prop type: ' +
242-
'Invalid prop `color` of type `number` supplied to `MyComp`, ' +
243-
'expected `string`.\n' +
233+
'Each child in a list should have a unique "key" prop. ' +
234+
'See https://reactjs.org/link/warning-keys for more information.\n' +
244235
' in MyComp (at **)\n' +
245236
' in ParentComp (at **)',
246237
);
@@ -328,125 +319,6 @@ describe('ReactElementValidator', () => {
328319
]);
329320
});
330321

331-
it('should check default prop values', async () => {
332-
class Component extends React.Component {
333-
static propTypes = {prop: PropTypes.string.isRequired};
334-
static defaultProps = {prop: null};
335-
render() {
336-
return React.createElement('span', null, this.props.prop);
337-
}
338-
}
339-
340-
await expect(async () => {
341-
const root = ReactDOMClient.createRoot(document.createElement('div'));
342-
await act(() => root.render(React.createElement(Component)));
343-
}).toErrorDev(
344-
'Warning: Failed prop type: The prop `prop` is marked as required in ' +
345-
'`Component`, but its value is `null`.\n' +
346-
' in Component',
347-
);
348-
});
349-
350-
it('should not check the default for explicit null', async () => {
351-
class Component extends React.Component {
352-
static propTypes = {prop: PropTypes.string.isRequired};
353-
static defaultProps = {prop: 'text'};
354-
render() {
355-
return React.createElement('span', null, this.props.prop);
356-
}
357-
}
358-
359-
await expect(async () => {
360-
const root = ReactDOMClient.createRoot(document.createElement('div'));
361-
await act(() =>
362-
root.render(React.createElement(Component, {prop: null})),
363-
);
364-
}).toErrorDev(
365-
'Warning: Failed prop type: The prop `prop` is marked as required in ' +
366-
'`Component`, but its value is `null`.\n' +
367-
' in Component',
368-
);
369-
});
370-
371-
it('should check declared prop types', async () => {
372-
class Component extends React.Component {
373-
static propTypes = {
374-
prop: PropTypes.string.isRequired,
375-
};
376-
render() {
377-
return React.createElement('span', null, this.props.prop);
378-
}
379-
}
380-
381-
const root = ReactDOMClient.createRoot(document.createElement('div'));
382-
await expect(async () => {
383-
await act(() => root.render(React.createElement(Component)));
384-
await act(() => root.render(React.createElement(Component, {prop: 42})));
385-
}).toErrorDev([
386-
'Warning: Failed prop type: ' +
387-
'The prop `prop` is marked as required in `Component`, but its value ' +
388-
'is `undefined`.\n' +
389-
' in Component',
390-
'Warning: Failed prop type: ' +
391-
'Invalid prop `prop` of type `number` supplied to ' +
392-
'`Component`, expected `string`.\n' +
393-
' in Component',
394-
]);
395-
396-
// Should not error for strings
397-
await act(() =>
398-
root.render(React.createElement(Component, {prop: 'string'})),
399-
);
400-
});
401-
402-
it('should warn if a PropType creator is used as a PropType', async () => {
403-
class Component extends React.Component {
404-
static propTypes = {
405-
myProp: PropTypes.shape,
406-
};
407-
render() {
408-
return React.createElement('span', null, this.props.myProp.value);
409-
}
410-
}
411-
412-
await expect(async () => {
413-
const root = ReactDOMClient.createRoot(document.createElement('div'));
414-
await act(() =>
415-
root.render(React.createElement(Component, {myProp: {value: 'hi'}})),
416-
);
417-
}).toErrorDev(
418-
'Warning: Component: type specification of prop `myProp` is invalid; ' +
419-
'the type checker function must return `null` or an `Error` but ' +
420-
'returned a function. You may have forgotten to pass an argument to ' +
421-
'the type checker creator (arrayOf, instanceOf, objectOf, oneOf, ' +
422-
'oneOfType, and shape all require an argument).',
423-
);
424-
});
425-
426-
it('should warn if component declares PropTypes instead of propTypes', async () => {
427-
class MisspelledPropTypesComponent extends React.Component {
428-
static PropTypes = {
429-
prop: PropTypes.string,
430-
};
431-
render() {
432-
return React.createElement('span', null, this.props.prop);
433-
}
434-
}
435-
436-
await expect(async () => {
437-
const root = ReactDOMClient.createRoot(document.createElement('div'));
438-
await act(() =>
439-
root.render(
440-
React.createElement(MisspelledPropTypesComponent, {prop: 'Hi'}),
441-
),
442-
);
443-
}).toErrorDev(
444-
'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' +
445-
'instead of `propTypes`. Did you misspell the property assignment?',
446-
{withoutStack: true},
447-
);
448-
});
449-
450322
it('warns for fragments with illegal attributes', async () => {
451323
class Foo extends React.Component {
452324
render() {

0 commit comments

Comments
 (0)