I've focused on validating the type of property values so far, but that's not always what you'll want to check for. Sometimes, specific values matter. Let's see how you can validate specific property values:
import React from 'react';
import PropTypes from 'prop-types';
// Any one of these is a valid "level"
// property value.
const levels = new Array(10).fill(null).map((v, i) => i + 1);
// This is the "shape" of the object we expect
// to find in the "user" property value.
const userShape = {
name: PropTypes.string,
age: PropTypes.number
};
const MyComponent = ({ level, user }) => (
<section>
<p>{level}</p>
<p>{user.name}</p>
<p>{user.age}</p>
</section>
);
// The property spec for this component uses
// "oneOf()" and "shape()" to define the required
// property values.
MyComponent.propTypes = {
level: PropTypes.oneOf(levels),
user: PropTypes.shape(userShape)
};
export default MyComponent;
The level property is expected to be a number from the levels array. This is easy to validate using the oneOf() function. The user property is expecting a specific shape. A shape is the expected properties and types of an object. The userShape defined in this example requires a name string and an age number. The key difference between shape() and instanceOf() is that you don't necessarily care about the type. You might only care about the values that are used in the JSX of the component.
Let's take a look at how this component is used:
import React from 'react';
import { render } from 'react-dom';
import MyComponent from './MyComponent';
render(
<section>
{/* Works as expected. */}
<MyComponent level={10} user={{ name: 'Name', age: 32 }} />
{/* Works as expected, the "online"
property is ignored. */}
<MyComponent user={{ name: 'Name', age: 32, online: false }} />
{/* Fails. The "level" value is out of range,
and the "age" property is expecting a
number, not a string. */}
<MyComponent level={11} user={{ name: 'Name', age: '32' }} />
</section>,
document.getElementById('root')
);
Here's what the component looks like when it's rendered:
