ReactJS - PropTypes



JavaScript is a dynamically typed language. It means that JavaScript does not need the type of a variable to be declared or specified. During program execution (Runtime), JavaScript checks the value assigned to variable and then it infers the type of the variable. For example, if a variable, num is assigned to John, then it infers that the type of num is string. If the same variable, num is assigned to 10, then it infers that the type of num is number.

var num = 'John' // The type of `num` is string
var num = 10     // The type of `num` is number

Dynamic typing is good for scripting language as it speeds up the development. The flip side of the dynamic typing is that the JavaScript engine does not know the type of a variable before it start executing the program. This prevent the JavaScript engine to find or identify certain bugs. For example, the below mentioned code does not execute and stops the program.

var num = 10
var name = 'John'
var result = num + name // throws error during runtime

React and types

In React, each component will have multiple props and each props should be assigned to value with correct type. Component props with wrong type will throw unexpected behavior. To better understand the problem, let us create a new application and create a component, which sums its properties and shows the result.

To create a new React app, execute below command,

create-react-app myapp

Once the application is created, create a new component, Sum under component folder (src/components/PropTypes/Sum.js)

import React from 'react'
class Sum extends React.Component {
   render() {
      return <p>The sum of {this.props.num1} and {this.props.num2}
      is {parseInt(this.props.num1) + parseInt(this.props.num2)}</p>
   }
}
export default Sum

Here, Sum component accept two number, num1 and num2 and prints the summation the given two number. The component will work if it is provided the number value for the props. But, if sum component is supplied with string then it will show NaN as the sum of the two properties.

Their is no way to find that the given value for num1 and num2 props are not in correct format. Let us use Sum component in the our root component (src/App.js) and see how it renders.

import Sum from "./components/PropTypes/Sum";
function App() {
   var num1 = 10
   var num2 = 200
   var name1 = "John"
   var name2 = "Peter"
   return (
      <div>
         <Sum num1={num1} num2={num2} />
         <Sum num1={name1} num2={name2} />
      </div>
   );
}
export default App;
PropTypes

PropTypes

React community provides a special package, prop-types to address the properties type mismatch problem. prop-types allows the properties of the component to be specified with type through a custom setting (propTypes) inside the component. For example, properties with number type can specified using PropTypes.number option as shown below.

Sum.propTypes = {
   num1: PropTypes.number,
   num2: PropTypes.number
}

Once the type of the properties is specified, then the React will throw warning during the development phase of the application. Let us include propTypes in our sample application and see how it helps to catch properties type mismatch issue.

Install prop-types package using node package manager (npm) as shown below −

npm i prop-types --save

Now, specify the type of the properties of Sum component as shown below −

import React from 'react'
import PropTypes from 'prop-types'
class Sum extends React.Component {
   render() {
      return <p>The sum of {this.props.num1} and {this.props.num2}
      is {parseInt(this.props.num1) + parseInt(this.props.num2)}</p>
   }
}
Sum.propTypes = {
   num1: PropTypes.number,
   num2: PropTypes.number
}
export default Sum

Finally, run the application using below command −

npm start

Open the application in your favorite browser and open the JavaScript console through developer tools. JavaScript throws the warning that the unexpected type is provided as shown below −

PropTypes

propTypes only works during development phase to nullify the performance reduction of the application due to additional checking of the props types. This will not affect the performance of the application in production / live setup.

Available validators

prop-types supplies a good collection of ready-made validators. They are as follows −

  • PropTypes.array

  • PropTypes.bigint

  • PropTypes.bool

  • PropTypes.func

  • PropTypes.number

  • PropTypes.object

  • PropTypes.string

  • PropTypes.symbol

  • PropTypes.node - Anything that can be rendered

  • PropTypes.element - React component

  • PropTypes.elementType - Type of React component

  • PropTypes.instanceOf() - instance of the specified class

  • propTypes.oneOf(['Value1', 'valueN']) - one of Value and ValueN

  • PropTypes.oneOfType([]) - Example, PropTypes.oneOfType([PropTypes.number, PropTypes.bigint])

  • PropTypes.arrayOf() - Example, PropTypes.arrayOf(PropTypes.number)

  • PropTypes.objectOf() - Example, PropTypes.objectOf(PropTypes.number)

  • PropTypes.func.isRequired

  • propTypes.element.isRequired

  • PropTypes.any.isRequired

A custom validator can also be created and used to validate the property's value. Let us consider that the component have a email property and the value should be a valid email address. Then, a validate function can be written and attached to the email property as shown below −

PropTypes
Sum.propTypes = {
   num1: PropTypes.number,
   num2: PropTypes.number,
   email: function(myProps, myPropName, myComponentName) {
      if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(myProps[myPropName])) {
         return new Error(
            'Invalid prop value `' + myProps[myPropName] + '` supplied to' +
            ' `' + myComponentName + '/' + myPropName + '`. Validation failed.'
         );
      }
   }
}

Here,

  • /^[^\s@]+@[^\s@]+\.[^\s@]+$/ is a simple regex email pattern.

  • myProps represents all properties.

  • myPropName represent the current property being validated.

  • myComponentName represent the name of the component being validated.

Similarly, custom validator can be created and used for array and object properties using below function signature

PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) { ... })
Advertisements