How to TypeCheck Your React Props

Published Mar 26, 2018

This is the third text that is about React props. Previously I've written about how to pass props in react and also how to indirectly communicate between components using props. Today, we're getting to the finale of props guide series, where I'll talk about how to check whether you passed correct props.

React props - Make sure you are typechecking

As the application you're working on grows, you'll definitely want to add some kind of prop typechecking - you don't want bugs you'll work on for hours or days before you realize you just sent an empty array instead of an object!

You can be a bit more extreme and use something like Typescript to cover your whole app with checks. While TypeScript can be quite useful and nice, there's no need for this - you don't need to enforce typechecking of every single function and variable.

Defining PropTypes is not enough! Make sure you're also covering your code with tests!

React has built-in PropTypes so you can typecheck easily. Basically, the idea is that inside of propTypes you define the type for each of the props used in the component. Here's the example component you'll be defining PropTypes for:

class Input extends Component {
    ...
    handleChange = (event) => {
        const newValue = event.target.value;
        this.props.updateParent(newValue);
    }
    ...
    render() {
        return (
            <input
                onChange={this.handleChange}
                placeholder={this.props.placeholder}
                type="text"
                value={this.props.value}
            />
        )
    }
}

The propTypes will look like this:

    Input.propTypes = {
        placeholder: PropTypes.string,
        updateParent: PropTypes.func.isRequired,
        value: PropTypes.string.isRequired,
    };

You have probably noticed that for updateParent and value I am using isRequired after prop type definition. This is to specify that the prop must be passed to a component, and that something will probably break if it's not done so.

If rendering a list sent as a prop, always make sure it's either required or default value is set!

On the other hand, a placeholder is not required. For optional props like this one, you might want to define a default value when nothing is pressed. You can achieve that by defining defaultProps for a component:

    Input.defaultProps = {
        placeholder: "Default placeholder",
    };

Besides the standard types, you can also add a typecheck whether a prop is an instance or some class:

   Parent.propTypes = {
        inputChild: PropTypes.instanceOf(Input),
    };

You can, as well, specify that prop can be any data type, by using PropTypes.any:

   Parent.propTypes = {
       anyValue: PropTypes.any,
   };

Try to avoid any, it's like not defining prop types at all - if you pass an empty array instead of an actual false value, that conditional rendering won't work as you expect!

PropTypes do not limit you to use just predefined type validators, you can also define your own. For more useful information on typechecking, take a look at the official guide, as it contains all the answers to questions you might have.

For all of the issues found while typechecking you will get notified in a console.

I strongly recommend that you configure eslint to require props validations for all components. This way you won't forget to define propTypes for your components, so you won't miss out some of the accidental issues you might have made during the coding.

You can also configure eslint to enforce defining of default values for props that are not required if you prefer to. This, although nice to have for consistency over the component instances, is not of such a big importance.

I hope you enjoyed this article and learned something new and useful, or at least freshened up your knowledge a bit!

This article is originally published on Kolosek Blog.

Discover and read more posts from Mark_S
get started