Type Checking With React PropTypes

John Au-Yeung - Jan 20 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

In this article, we’ll look at how to valid prop data types by using PropTypes .

Type Checking With PropType

As our code grows, we can catch a lot of bugs with type checking.

React has built-in type checking abilities for props.

We can add prop type checks as follows:

import React from "react";  
import ReactDOM from "react-dom";  
import PropTypes from "prop-types";

class Greeting extends React.Component {  
  render() {  
    return <p>Hello, {this.props.name}</p>;  
  }  
}

Greeting.propTypes = {  
  name: PropTypes.string  
};

class App extends React.Component {  
  render() {  
    return <Greeting name="Jane" />;  
  }  
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have:

Greeting.propTypes = {  
  name: PropTypes.string  
};
Enter fullscreen mode Exit fullscreen mode

to check that the name prop passed in is a string.

In addition to strings, it has many other kinds of validations that can be used to make sure that data received is valid.

When an invalid value is provided for a prop, a warning will be shown in the JavaScript console.

Prop type checks are only run in development mode for performance reasons.

PropTypes

In addition to strings, there’re many more prop types available. They’re the following:

  • PropTypes.array — checks for arrays
  • PropTypes.bool — checks for boolean
  • PropTypes.func — checks for functions
  • PropTypes.number — checks for number
  • PropTypes.object — checks for object
  • PropTypes.string — checks for string
  • PropTypes.symbol — checks for symbol
  • PropTypes.node — checks for anything that can be rendered
  • PropTypes.element — checks for a React element
  • PropTypes.elementType — checks for a React element type (e.g. Component )
  • PropTypes.instanceOf(Foo) — checks for instance of a class, in this case, Foo
  • PropTypes.oneOf([‘foo’, ‘bar’]) — checks for one of the values in the array
  • PropTypes.oneOfType([PropTypes.string, PropTypes.number]) — checks for one of the types in the array
  • PropTypes.arrayOf(PropTypes.number) — checks for an array of the given type
  • PropTypes.shape({color: PropTypes.string, fontSize: PropTypes.number } — checks for an object with these properties and types of values
  • PropTypes.exact({ name: PropTypes.string, quantity: PropTypes.number }) — checks for an object with these properties and types of values with warnings on extra properties
  • isRequired — set a prop as being required, e.g. we can use is by writing PropTypes.func.isRequired to make a prop that takes a function required.

We can also set our own prop validation function as follows:

class Greeting extends React.Component {  
  render() {  
    return <p>Hello, {this.props.name}</p>;  
  }  
}

Greeting.propTypes = {  
  name(props, propName, componentName) {  
    if (!["Jane", "Joe"].includes(props[propName])) {  
      throw new Error("Invalid name");  
    }  
  }  
};

class App extends React.Component {  
  render() {  
    return <Greeting name="Foo" />;  
  }  
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have:

Greeting.propTypes = {  
  name(props, propName, componentName) {  
    if (!["Jane", "Joe"].includes(props[propName])) {  
      throw new Error("Invalid name");  
    }  
  }  
};
Enter fullscreen mode Exit fullscreen mode

which has the name function where we can check the name prop to see if it’s set to 'Jane' or 'Joe' .

If it’s not, like the example above, we’ll get the warning:

Warning: Failed prop type: Invalid name
Enter fullscreen mode Exit fullscreen mode

in the JavaScript console.

Requiring Single Child

We can specify that only a single child can be passed to a component as children.

To do this, we write:

class Greeting extends React.Component {  
  render() {  
    return <p>Hello, {this.props.children}</p>;  
  }  
}

Greeting.propTypes = {  
  children: PropTypes.element.isRequired  
};

class App extends React.Component {  
  render() {  
    return <Greeting>Jane</Greeting>;  
  }  
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we specified that children has the type PropTypes.element.isRequired , which means that we check if only one element is passed in.

Default Prop Values

We can also set default values for props.

For instance, we can write:

class Greeting extends React.Component {  
  render() {  
    return <p>Hello, {this.props.name}</p>;  
  }  
}

Greeting.defaultProps = {  
  name: "Jane"  
};

class App extends React.Component {  
  render() {  
    return <Greeting />;  
  }  
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have the defaultProps property set for Greeting to set the default props.

Since we didn’t pass any value for the name prop to Greeting , React will set the name prop to 'Jane' by default, so we get Hello, Jane.

If we change 'Jane' to 'Joe' , then we get Hello, Joe instead.

Conclusion

We can use prop types to check the types for our props. This prevents us from passing in data that we don’t want, preventing potential bugs.

Prop types can check for many types, including any JavaScript type, like numbers, objects, and symbols.

It can also check the structure of objects and arrays, and also checks if specific values are passed in.

In addition, we can make our own validator function to check what they’re and throw an error to reject invalid values.

We can add prop type check for children to validate what’s passed in between tags.

Also, we can set a default value for props, by setting a value for it in the defaultProps object.

Finally, we can use isRequired to check for if a prop value is passed in.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .