Table of Contents
We all want to develop applications perfectly without too many bugs. Unlike C or C++, JavaScript is a weak-typed language. A variable containing a number can be assigned a string value without throwing an error. Interestingly, this is the cause of 80% of the bugs.
Once you start using props in your applications, it becomes critical to validate them and ensure that they are in the intended form.
What is Prop Validation in React?
Prop validation is the action of checking if the received props are valid and acceptable. It can be a simple check, such as the following:
- Verifying if the data type of the prop matches the intended type.
- Determining if a prop is equal to some value.
- Making sure a prop is not undefined or null.
There is no strict rule on how you validate your props. You can validate props inside a class component or even outside it, as we will see in the later section.
Benefits of Validating Props
1. Potential to catch bugs early in your application.
2. Saves cost and time by removing the need to check for errors caused by bad props.
3. Encourages a good habit right from the beginning for type checking props and handling errors.
There are two ways you can perform prop validation:
1. Doing custom (user-defined) validation yourself by using JavaScript methods.
2. Using a library like PropTypes, TypeScript, or Flow.
Let’s look at both of them.
User-Defined Prop Validation
You can utilize the built-in JavaScript functions to perform advance and straightforward checks, depending on your requirement. Here are some of the common JavaScript language validation:
1. Checking for prop existence
This check will ensure that a prop is not undefined. Using this validation will save you from the common error: “Cannot read property of undefined”.
if (props.propName) { // propName exists, and you can proceed further }
2. Check the prop type using JavaScript
Using the typeof
operator in JavaScript, we can determine the prop’s type and perform different actions according to your requirement.
if (typeof props.propName === 'string') { // propName is a string type value… }
3. JavaScript methods
There are a plethora of methods like .includes()
, .test()
, .match()
, etc. which you can use to perform checks in your components.
if (props.propName.includes('hello')) { // propName exists and includes the word "hello" in it. } // or test if password needs to have special characters if (/[^a-z0-9]/.test(props.password)) { // password prop includes special characters… // do something here } else { // password prop does not include special characters… // do something else here }
defaultProps and propTypes
You can define two properties on any Component to deal with props. They are:
- defaultProps
- propTypes
“defaultProps”
Using the “defaultProps” property, we can specify default values for props, so that even if a prop is not passed, the Component will be able to use those default values to prevent an error.
function MyComponent(props) { return ( <div> <h1> Hello { props.username } </h1> </div> ) } /**** Specify defaultProps as a property of the Component ****/ MyComponent.defaultProps = { username: 'Guest' }
Once you define the defaultProps object, props’ default values will be used unless it is overridden. Take a look at the illustration below.
“propTypes”
There is one more property called propTypes that you can add to a Component. With this property, you can validate props by using a custom validator function.
The custom validator function must return an Error object if it is not valid. The example below checks if the username prop is a string.
MyComponent.propTypes = { username: (props, propName, componentName) => { /** logic to check if 'username' is a string **/ if (typeof props[propName] !== 'string') { return new Error(propName + ‘must be a string’); } } }
Every property that you put in the propTypes object will be checked. However, it is very cumbersome to write code for checking even the most basic types like string, number, etc.
That’s why we have a library called PropTypes that helps us to avoid writing our custom validator functions.
Library based prop validation (PropTypes)
First, install the PropTypes library in your react project by running the command below:
npm install prop-types
We can validate props ourselves without using any libraries, but it is inefficient to use them every time unless it’s a specific case. That’s why we need libraries like PropTypes.
The diagram below shows the flow of prop validation.
The PropTypes library is to be used together with the “propTypes” property. It provides useful built-in validators that we can use. Here are the most common validators:
1. Check if the prop is a number:
PropTypes.number
2. Check if the prop is a string:
PropTypes.string
3. Check if the prop is a boolean:
PropTypes.bool
4. Check if the prop is an array:
PropTypes.array
5. Check if the prop is an object:
PropTypes.object
6. Check if the prop is a function:
PropTypes.func
And on each of them, we can append a property called isRequired
. eg: PropTypes.string.isRequired
and PropTypes.number.isRequired
. Doing so ensures that the specific prop is required and must be passed.
Using PropTypes
Now, we need to import the library to our application and use it inside the propTypes object.
Instead of writing the vast confusing validator function to check a string or a number, you can use one of the string checking functions from the PropTypes library. Check the comparison of the two code blocks below.
/** Custom validator functions without PropTypes **/ MyComponent.propTypes = { username: (props, propName, componentName) => { /** logic to check if 'username' is a string **/ if (typeof props[propName] !== 'string') { return new Error(propName + 'must be a string'); } }, someNumber: (props, propName, componentName) => { /** logic to check if "someNumber" is defined and is a number **/ if (props[propName] && typeof props[propName] !== 'number' ) { return new Error(propName + 'must be a number'); } } } /** Using PropTypes is far more simpler **/ import PropTypes from 'prop - types'; MyComponent.propTypes = { username: PropTypes.string, someNumber: PropTypes.number.isRequired, }
You are now all set with prop validation. Any prop validation error will be logged to the console.
Summary
Prop validation is not necessary for a small application. It is really helpful for medium-scale applications as it greatly reduces the number of bugs.
For large-scale applications, it is more advantageous to use strong-typed languages like TypeScript or Flow in addition to PropTypes.