Typechecking With React PropTypes
Validating React props: A good way to help you catch bugs and improve the way you receive props.
Some housekeeping: This blog will assume you have some basic Reactjs knowledge. If you happen to need a quick refresher or rundown on the basics, then check out my ReactJs Basics blog here.
Props are vital for passing attributes to React components. These attributes are most often expected to be of a certain type for proper use in a component. If a prop is passed to a component other than it’s original purpose, the component may not behave as expected or effectively. Thus, prop validations are a great way of improving React components.
What is React PropTypes?
PropTypes are a feature for runtime validation of props during development.
According to the official Reactjs documentation:
PropTypes
exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. For performance reasons,propTypes
is only checked in development mode.
You can declare a prop is a specific Javascript type such as arrays, booleans, numbers, strings, even nodes or instances of a class. This in turns creates a validation check for props that are passed into components. But why?
For every tool, there was a need or a reoccurring problem that needed a solution. In order to understand why React propTypes
exist and why we use them, we need to paint the problem.
Why use React PropTypes?
Now imagine, you’re building a library that you want to distribute to other people or you’re working in a big team where everyone has different components or containers they’re responsible for. Then you might have scenarios where people start using your component incorrectly because they don’t know the data type of the prop being passed. For example, your teammate Bob would like to reuse the post component you happily created and worked so hard on (After all, what would React be if we can’t reuse components?). But Bob can’t seem to render a post because he doesn’t know that he is passing in a string as props even though the property the component accepts is an array. If a prop validation were to exist, Bob would receive a nice big red warning in his console that he is passing in incorrect props.
Though this is a contrived example, you can see that propTypes
come in handy as your app grows, becomes more complex and involves other developers. Now if you are working on your own application and you’re working alone then propTypes
may not really be that useful because you obviously know which props your components take. However, prop validation might help when revisiting a project that you haven’t worked on in a while (so is leaving good comments!) but that's a whole different story.
Now that we got that out the way, let us explore how you can improve the way you’re receiving props. If you like to code along I’ve created a simple repo here or you can follow along with the visuals provided. Skip to the next section if you’d like to get straight into setting up//using propTypes
.
Let’s have a look at our App component.
import React, { Component } from "react";
import PersonGreeter from "./PersonGreeter";class App extends Component {
state = {
persons: [
{ id: 1, name: "Steven", age: 27 },
{ id: 2, name: "John", age: 2 },
{ id: 3, name: "Smith", age: 8 }
],
clicked: false
};clickHandler = () => {
this.setState({ clicked: !this.state.clicked });
};mapThroughPersonsArray = () => {
return this.state.persons.map((person, index) => (
<PersonGreeter
key={person.id}
person={person}
name={person.name}
age={person.age}
clicked={() => this.removePersonHandler(index)}
/>
));
};removePersonHandler = personIndex => {
const persons = [...this.state.persons];
persons.splice(personIndex, 1);
this.setState({ persons: persons });
};render() {
return (
<div className="app_heading">
<h1>Welcome to Person Greeter!</h1>
<button className="showButton" onClick={this.clickHandler}>
Show Persons
</button>
{this.state.clicked && this.mapThroughPersonsArray()}
</div>
);
}
}export default App;
Here we have a class component that contains a state with two keys: An array of objects with the property name of persons and clicked with a boolean value currently set as false. There is a clickHandler function that handles updating the clicked state as well as a mapThroughPersonsArray function which iterate’s through the array of objects and renders a PersonGreeter component for each person object in the array (Got to love dynamic components). Along with passing the person information into the child component, we are also passing in a reference to the removePersonHandler function.
Now let’s look at the PersonGreeter component.
Here PersonGreeter is receiving props and we access these props to display the information in h2
tags on our page as well as a button that handles the click event.
Now nothing wrong with the way we’re setting this up but we can improve our application to be more clear about which props the component accepts and make it throw a warning if incorrect props are passed in.
Setting up PropTypes and How to use
Note:
React.PropTypes
has moved into a different package since React v15.5. The React team extractedReact.PropTypes
andReact.createClass
into their own packages to reflect the fact that not everybody uses them, thus makingcreate-react-app
much lighter then previous versions.In 15.5 and beyond, instead of accessing
PropTypes
from the mainReact
object, we will install theprop-types
package and import them from there.
First, we install the package that is provided by the REACT team like so:
npm intall --save prop-types
Like I mentioned above, it’s not built into react core but it is part of react (for those worried about the package’s source)
Now once that finishes successfully, let’s visit the component we want to set our validations in- which in this case is PersonGreeter. You simply import PropTypes
(recommended with an uppercase character though not strictly required)
import PropTypes from 'prop-types'
This works in both functional and class-based components. So after our component definition, we will access our PersonGreeter component and add a new property called propTypes
with a lowercase p*.
PersonGreeter.propTypes = {};
Importing propTypes
provides us with a couple of data types we can use inside this object. We define which props this component uses and which data type the prop should be, by setting up key-value pairs where the keys are your prop names and by defining which type of value the prop should be.
Our PersonGreeter component receives name, age, and clicked as props and the expected values of these props are string, number, and function in that order. So let’s see how this looks in our component.
Here func stands for function which indicates to React that for a click event, I expect to get a pointer at a function and nothing else. Not a string, not a number but a function. For name, we add the string prop type and for age we add the number prop type since we expect the prop to be a number. Pretty simple right?
Now that we created this javascript object with propTypes
as a special property, React will watch out for this in development mode and give you a warning if you pass incorrect props.
Let’s break our application so we can watch this in action. In the state of our App component, let’s wrap the age of the Steven object with quotes, effectively switching the age data type from a number to a string. Now on our webpage, we wouldn’t see any changes but let’s open up the developer console to watch our validation work.
When clicking on Show Persons, we receive a warning in our console stating that the age prop expected type is a number but is a string. Now if someone uses your component incorrectly during development they will get a warning in the console and then they can fix their error.
And as I mentioned earlier, this is helpful in scenarios where you distribute your components as a package to other developers or where you’re working on a big team and it might not be super clear which props your components take and which type of data goes into which prop.
And that’s Typechecking with React PropTypes!
More with PropTypes
There are many different validators provided when importing PropTypes which you can see by logging in the console.
*A note on using propTypes in functional or class components. The instance of a PropTypes object is lowercase, but the Class/Type is uppercase. The instance is
List.propTypes
. The Class/Type isPropTypes
.
//Class componentList.PropTypes = {
todos: PropTypes.array.isRequired,
};//Instance of propType (In a functional component)List.propTypes = {
todos: PropTypes.array.isRequired,
};