React Prop Types
prop-types is a JavaScript library providing runtime type checking for React component props and similar object structures. It enables developers to define the expected types, shapes, and requirements for properties, issuing helpful warnings in development environments when mismatches occur. Its current stable version is 15.8.1. While once integrated directly into React, it was externalized in React v15.5 to encourage the adoption of static type checking solutions like TypeScript or Flow. prop-types continues to be maintained for projects that prefer runtime validation or are not yet using static typing, serving as a robust, albeit runtime-only, solution for ensuring data integrity within component APIs. It offers a comprehensive set of validators for primitives, instances, enums, arrays, objects, and more, making it flexible for various use cases. The library generally follows a stable release cadence, primarily for maintenance and compatibility updates rather than new features, given its mature state and the ecosystem's shift towards compile-time type checking.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'array')
cause The `PropTypes` object was not correctly imported or is undefined, leading to attempts to access properties (like `array`) on a non-existent object.fixEnsure you have `import PropTypes from 'prop-types';` (ES Modules) or `const PropTypes = require('prop-types');` (CommonJS) at the top of your file. -
Warning: Failed prop type: The prop `myProp` is marked as required in `MyComponent`, but its value is `undefined`.
cause A prop that was declared with `.isRequired` was either not provided to the component or was explicitly passed as `undefined`.fixProvide a value for the required prop when using the component, e.g., `<MyComponent myProp={someValue} />`, or ensure it's not `undefined` if optional. -
Warning: Failed prop type: Invalid prop `myProp` of type `string` supplied to `MyComponent`, expected `number`.
cause The actual type of the prop passed to the component does not match the type declared in `MyComponent.propTypes`.fixPass a prop of the correct type, e.g., `<MyComponent myProp={123} />` if `myProp` expects a `number`. -
ReferenceError: PropTypes is not defined
cause The `prop-types` library was not imported or included in the scope where it is being used.fixAdd the necessary import statement for `PropTypes` at the top of the file: `import PropTypes from 'prop-types';` or `const PropTypes = require('prop-types');`.
Warnings
- breaking In React v15.5, `PropTypes` was extracted from the `React` package into its own `prop-types` library. Direct access via `React.PropTypes` no longer works and will result in a runtime error.
- gotcha prop-types performs runtime checks and only provides warnings in development mode. It does not enforce types at compile-time and is not suitable for critical production validation or security checks.
- deprecated While still maintained, `prop-types` is considered a legacy solution by the React team, with a strong recommendation for developers to adopt static type checking solutions (like TypeScript or Flow) for new projects and substantial refactors.
- gotcha The `.shape()` validator allows additional properties beyond those defined in the shape. If you need to restrict an object to an exact set of properties, use the `.exact()` validator instead.
Install
-
npm install prop-types -
yarn add prop-types -
pnpm add prop-types
Imports
- PropTypes
import { PropTypes } from 'prop-types';import PropTypes from 'prop-types';
- PropTypes (CommonJS)
import PropTypes from 'prop-types';
const PropTypes = require('prop-types'); - Specific validators
MyComponent.propTypes = { optionalString: PropTypes.string };
Quickstart
import React from 'react';
import PropTypes from 'prop-types';
class MyMessage {
constructor(text) {
this.text = text;
}
}
class MyComponent extends React.Component {
render() {
// Example of using props inside render
return (
<div>
<p>String: {this.props.optionalString}</p>
<p>Number: {this.props.optionalNumber}</p>
<p>Enum: {this.props.optionalEnum}</p>
<p>Message Text: {this.props.optionalMessage ? this.props.optionalMessage.text : 'N/A'}</p>
<p>Required Property: {this.props.optionalObjectWithShape.requiredProperty}</p>
</div>
);
}
}
MyComponent.propTypes = {
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalNode: PropTypes.node,
optionalElement: PropTypes.element,
optionalElementType: PropTypes.elementType,
optionalMessage: PropTypes.instanceOf(MyMessage),
optionalEnum: PropTypes.oneOf(['News', 'Photos']).isRequired,
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(MyMessage)
]),
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
optionalObjectWithShape: PropTypes.shape({
optionalProperty: PropTypes.string,
requiredProperty: PropTypes.number.isRequired
}).isRequired,
// A required object with an exact set of properties and types
// This will warn if extra properties are supplied, unlike .shape
strictObject: PropTypes.exact({
a: PropTypes.number,
b: PropTypes.string.isRequired
})
};
// Example usage (in a React application)
// function App() {
// return (
// <MyComponent
// optionalString="hello"
// optionalNumber={123}
// optionalEnum="News"
// optionalMessage={new MyMessage('Hello from PropType!')}
// optionalObjectWithShape={{ requiredProperty: 42 }}
// strictObject={{ a: 1, b: 'two' }}
// />
// );
// }
// export default App;
// To prevent 'React' is defined but never used, mock a render if not in a React app context
if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') {
console.log('PropTypes example component defined. Run in a React app for full effect.');
}