Master PropTypes in React
A useful guide to React propTypes and type checking
React is a JavaScript library for building user interfaces. React makes it easier to manage the state of our application and efficiently updates the UI when the state changes.
React is component based and each component can have its own state (manipulated via setState()
) and can receive props (provided by the parent component).
Tip: Build React apps faster with reusable components. Use Bit to collect reusable components, share them with your team, and use them anywhere. Give it a try.
The Problem
Since React is a JavaScript library and JavaScript does not provide any type-checking, passing the wrong type of props to components can cause a lot of bugs in your application.
Solution
You can use JavaScript extensions like TypeScript for type checking, but if you don’t want to use it, React provides useful type-checking features to verify that components receive props of the correct type. Using PropTypes, we can make sure that components receive the right type of props.
For example, suppose we have a Person component which receives two props: name and age of the person. Using PropTypes, we can ensure that name is always a string and the age is always a number.
Installing PropTypes
To use PropTypes, we have to install a separate prop-types
package provided by React. For example:
npm install --save prop-types
OR
yarn add prop-types
Using PropTypes
To use PropTypes, we first have to import PropTypes
from the prop-types
package. For example:
import { PropTypes } from 'prop-types';
We can then define the propTypes
property on a component. For example:
MyComponent.propTypes = {};
Here propTypes
is an object which contains key-value pairs, where the key is the name of the prop and the value is the type of the prop that can be passed to the component.
Example
If we have a Student
component which receives 2 props: 1) name
of the student, and 2) age
of the student.
import React from 'react';
import { PropTypes } from 'prop-types';class Student extends React.Component {
render() {
return (
<div>
<p>Name: {this.props.name}</p>
<p>Age: {this.props.age}</p>
</div>
);
}
}
Using PropTypes, we can make sure that name
is always a string, and age
is always a number.
For example:
import React from 'react';
import { PropTypes } from 'prop-types';class Student extends React.Component {
render() {
return (
<div>
<p>Student Name: {this.props.name}</p>
<p>Age: {this.props.age}</p>
</div>
);
}
}Student.propTypes = {
name: PropTypes.string,
age: PropTypes.number
};export default Student;
Here PropTypes.string
and PropTypes.number
are prop validators which can be used to make sure props received are of the right type. PropTypes
has lots of validators, some of the most common use prop validators are:
MyComponent.propTypes = {
propArray: PropTypes.array,
propBool: PropTypes.bool,
propFunc: PropTypes.func,
propNumber: PropTypes.number,
propObject: PropTypes.object,
propString: PropTypes.string,
}
Passing Wrong Props
When a wrong or invalid prop is passed to the component, a warning or an error is shown in the JavaScript Console. For example:
import React from 'react';
import Student from './Student';class App extends React.Component { render() {
return (
<div>
<Student name="Mark" age="24" />
</div>
);
}
}export default App;
Here the age
prop is passed as a string to the Student
component. So React will show a warning in the JavaScript console. For example:
PropTypes in Class Components
There is no difference between using PropTypes
in class-based components versus functional components. For example:
import React from 'react';
import { PropTypes } from 'prop-types';class Student extends React.Component {
render() {
return (
<div>
<p>Student Name: {this.props.name}</p>
<p>Age: {this.props.age}</p>
</div>
);
}
}Student.propTypes = {
name: PropTypes.string,
age: PropTypes.number
};export default Student;
PropTypes in Functional Components
import React from 'react';
import { PropTypes } from 'prop-types';const Student = (props) => {
return (
<div>
<p>Student Name: {props.name}</p>
<p>Age: {props.age}</p>
</div>
);
};Student.propTypes = {
name: PropTypes.string,
age: PropTypes.number
};export default Student;
Requiring Props
Apart from specifying the type of the prop that can be passed to the component, we can also make sure the prop is always provided to the component by chaining isRequired
at the end of the prop validator.For example:
import React from 'react';
import { PropTypes } from 'prop-types';class Student extends React.Component {
render() {
return (
<div>
<p>Student Name: {this.props.name}</p>
<p>Age: {this.props.age}</p>
</div>
);
}
}Student.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number
};export default Student;
A warning will be shown to the console if the name
prop is not provided to the Student
component. For example:
import React from 'react';
import Student from './Student';class App extends React.Component {render() {
return (
<div>
<Student age="24" />
</div>
);
}
}export default App;
Here the name
prop is not passed to the component, so React will display a warning. For example:
Requiring Single Child
We can use PropTypes.element
to enforce that only a single child can be passed to a component as children. For example:
import React from 'react';
import { PropTypes } from 'prop-types';class Container extends React.Component {render() {
return (
<div>
{this.props.children}
</div>
);
}
}Container.propTypes = {
children: PropTypes.element
};export default Container;
If we try to pass more than 1 child to the component, we will get an error. For example:
import React from 'react';
import Container from './Container';
import Student from './Student';class App extends React.Component {render() {
return (
<div>
<Container>
<Student name="Mark" age="24" />
<Student name="Peter" age="25" />
</Container>
</div>
);
}
}export default App;
Advance PropTypes Validators
Apart from specifying whether a prop should be an array or an object, we can use these prop validators to specify which type of array or object can be passed as a prop. For example:
PropTypes.arrayOf()
We can use PropTypes.arrayOf()
to specify which type of array can be passed as a prop. For example:
import React from 'react';
import { PropTypes } from 'prop-types';class Numbers extends React.Component {
render() {
const numbers = this.props.numbers.map(number => <p>{number}</p>);
return (
<div>
{numbers}
</div>
);
}
}Numbers.propTypes = {
numbers: PropTypes.arrayOf(PropTypes.number)
};export default Numbers;
Here only an array of number type can be passed as a prop. If we try to pass wrong type of array as a prop, we’d get a warning. For example:
import React from 'react';
import Numbers from './Numbers';class App extends React.Component {render() {
return (
<div>
<Numbers numbers={['1', '2', '3']} />
</div>
);
}
}export default App;
PropTypes.objectOf()
Similar to PropTypes.arrayOf()
we can use PropTypes.objectOf()
to specify which type of object can be passed as a prop to the component. For example:
NamesList.propTypes = {
names: PropTypes.objectOf(PropTypes.string)
}
Here, the only object which contains string
type values can be passed as a prop to the component.
Conclusion
We have learned what PropTypes are and how to use them for type-checking. While you may not find type-checking useful for small applications, it can avoid a lot of bugs if your application is fairly large.
That’s it and I hope you found this article helpful. If you have any questions, please feel free to comment! I’d be happy to help :) You can also follow me on Medium and Twitter. Thanks for reading! 😃