Go back

Using PropTypes in React

React is a popular JavaScript library for building user interfaces. One important aspect of building stuff with React is ensuring that the props (short for properties) passed to components are valid. This is where propTypes comes in.

PropTypes is a way of specifying the type of a prop that a component expects to receive. By using propTypes, we can catch type errors during development, making our code more robust and easier to maintain.

The snippet below is an example of a simple Hello component that expects to receive a name prop of type string:

import React from 'react'
import PropTypes from 'prop-types'
 
function Hello(props) {
  return <h1>Hello, {props.name}</h1>
}
 
Hello.propTypes = {
  name: PropTypes.string,
}

Notice how the props argument is passed in the component above. We can proceed to destructure the prop object so that it becomes easier for us to access the properties. The snippet above becomes:

function Hello({ name }) {
  return <h1>Hello, {name}</h1>
}
 
Hello.propTypes = {
  name: PropTypes.string,
}

We can use this component like so:

<Hello name="John" />

This will render a <h1> element with the text "Hello, John".

If we try to pass a prop of the wrong type to the Hello component, we will get a warning in the console during development. For example, if we pass a number instead of a string:

<Hello name={42} />

This will produce a warning in the console that says "Invalid prop name of type number supplied to Hello, expected string."

PropTypes provides several types that we can use to specify the expected type of a prop. In addition to string, there are types for numbers, bool, arrays, objects, and others. We can also specify that a prop is required by using the isRequired modifier. For example:

Hello.propTypes = {
  name: PropTypes.string.isRequired,
}

Now, if we forget to pass the name prop to the Hello component, we will get a warning in the console that says "The prop name is marked as required in Hello, but its value is undefined."

In addition to basic types, PropTypes also allows us to specify more complex types. For example, we can use the shape type to specify the exact structure of an object prop:

function User({ user: { name, email } }) {
  return (
    <div>
      <p>Name: {name}</p>
      <p>Email: {email}</p>
    </div>
  )
}
 
User.propTypes = {
  user: PropTypes.shape({
    name: PropTypes.string.isRequired,
    email: PropTypes.string.isRequired,
  }).isRequired,
}

In the snippet above, the User component expects to receive a user prop that is an object with name and email properties. If we try to pass a user prop that is missing one of these properties or has the wrong type, we will get a warning in the console.

Notice how the properties are destructured. Instead of using the dot notation to access the variables like this props.user.email, we have access to them without the repetitive process. I wrote something related to destructuring object properties in react, you can take a look at it here to learn more.

Available Prop Types

The prop-types module provides several different prop-type validation functions that you can use to validate the props passed to a component. Here's a list of the most commonly used prop-type validation functions:

PropTypes.string: Validates that the prop is a string.

PropTypes.number: Validates that a prop is a number.

PropTypes.bool: Validates that the prop is a boolean value (i.e., true or false).

PropTypes.array: Validates that the prop is an array.

PropTypes.object: Validates that a prop is an object.

PropTypes.func: Validates that the prop is a function.

Using default props

In the same way, we use props to specify the type of data a component receives, default props are used to define the prop value(s) that a component can fall back to when a value has not been set explicitly.

Say you have a Button component, for example, that accepts a text prop. If you forget to assign the appropriate value to the component, the default prop is used as a fallback option. The snippet below illustrates this;

Button.defaultProps = {
  text: 'Send',
}

You can have more than one default prop, as your needs expand. When you go ahead and import the button component without the text prop, the text "Send" is rendered in the button.

<Button /> // renders the component with an accompanying "Send" text

Likewise, you can also proceed with your custom text

<Button text="Submit" />

Wrapping up.

Tapping into the defaultProps superpower of the prop-type module can make your development process a little bit hectic, and type-safe. Although, there are lots of opinions around the use of PropTypes when we have TypeScript. As a beginner yourself, I'd recommend you start with the fundamentals of using the prop-type module before jumping around.

Thank you for reading this article, and I hope you'd find it helpful.