VOOZH about

URL: https://blog.logrocket.com/validate-react-props-proptypes/

โ‡ฑ How to validate React props using PropTypes - LogRocket Blog


2022-08-17
2378
#react
Glad Chinda
366
๐Ÿ‘ Image

See how LogRocket's Galileo AI surfaces the most severe issues for you

No signup required

Check it out

Editorโ€™s note: This article was last updated 17 August 2022 to verify code accuracy.

๐Ÿ‘ React Prop Types Validate Props

Props and PropTypes are important mechanisms for passing read-only attributes between React components.

We can use React props, short for properties, to send data from one component to another. If a component receives the wrong type of props, it can cause bugs and unexpected errors in your app.

Since JavaScript doesnโ€™t have a built-in type checking solution, many developers use extensions like TypeScript and Flow. However, React has an internal mechanism for props validation called PropTypes. In this article, weโ€™ll learn how to validate props with React PropTypes.

If youโ€™re more of a visual learner, I recommend checking out the following video tutorial on React PropTypes:

Validating React component props with prop-types

Learn how to improve your React components by validating props with prop-types Introduction โ€“ 00:00 Getting started with prop-types โ€“ 01:24 Validating component props with prop-types โ€“ 03:17 Try LogRocket for free: https://logrocket.com/?yt24 Github repo: https://github.com/karlhadwen/react-proptypes LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser.

๐Ÿš€ Sign up for The Replay newsletter

The Replay is a weekly newsletter for dev and engineering leaders.

Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.

How do React props work?

With React props, you can send data to a component when you call on that component, including numbers, strings, functions, objects, and arrays. If you have multiple components, you can pass data from one component to another.

To pass props between components, you can add them when the component is called, just like you would pass arguments when calling on a regular JavaScript function.

Why should you validate props in React?

When developing a React application, youโ€™ll need to structure and define your props to avoid bugs and errors. Just like a function might have mandatory arguments, a React component might require a prop to be defined, otherwise, it will not render properly. Forgetting to pass a required prop into a component that needs it could cause your app to behave unexpectedly.

Consider the code below:

import React from 'react';
import ReactDOM from 'react-dom';

function PercentageStat({ label, score = 0, total = Math.max(1, score) }) {
 return (
 <div>
 <h6>{ label }</h6>
 <span>{ Math.round(score / total * 100) }%</span>
 </div>
 )
}

function App() {
 return (
 <div>
 <h1>Male Population</h1>
 <div>
 <PercentageStat label="Class 1" total={360} score={203} />
 <PercentageStat label="Class 2" total={206} />
 <PercentageStat label="Class 3" score={107} />
 <PercentageStat label="Class 4" />
 </div>
 </div>
 )
}

const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);

In the code above, the PercentageStat component requires three props to render properly, label, score, and total. Default values are set for the score and total props in case they are not provided. PercentageStat is rendered four times in the App component, each time with different props.

The image below shows what the app would look like with some additional Bootstrap styling:

๐Ÿ‘ React Props App Bootstrap Styling

Based on usage, the label prop is expected to be a string. In the same vein, score and total are required to be numeric values since they are used for computing percent. In addition, total is expected to never be 0 since it is being used as a divisor.

The code below shows a modified app that renders PercentageStat components with invalid props:

function App() {
 return (
 <div>
 <h1>Male Population</h1>
 <div>
 <PercentageStat label="Class 1" total="0" score={203} />
 <PercentageStat label="Class 2" total={0} />
 <PercentageStat label="Class 3" score={f => f} />
 <PercentageStat label="Class 4" total={{}} score="0" />
 </div>
 </div>
 )
}

Now, the app view looks like the following image:

๐Ÿ‘ React App Invalid Props Display

Using PropTypes in React

PropTypes is Reactโ€™s internal mechanism for adding type checking to component props. React components use a special property called propTypes to set up type checking:

/**
 * FUNCTIONAL COMPONENTS
 */
function ReactComponent(props) {
 // ...implement render logic here
}

ReactComponent.propTypes = {
 // ...prop type definitions here
}


/**
 * CLASS COMPONENTS: METHOD 1
 */
class ReactComponent extends React.Component {
 // ...component class body here
}

ReactComponent.propTypes = {
 // ...prop type definitions here
}


/**
 * CLASS COMPONENTS: METHOD 2
 * Using the `static` class properties syntax
 */
class ReactComponent extends React.Component {
 // ...component class body here

 static propTypes = {
 // ...prop type definitions here
 }
}

When props are passed to a React component, they are checked against the type definitions configured in the propTypes property. When an invalid value is passed for a prop, a warning is displayed on the JavaScript console:

๐Ÿ‘ Javascript Console Invalid Prop

If default props are set for the React component, the values are first resolved before type checking against propTypes. Therefore, default values are also subject to the prop type definitions.

Keep in mind that type checking propTypes can happen only in development mode, enabling you to catch bugs in your React application before releasing it to the production environment.

Using the prop-types library in React

Prior to React v15.5.0, a utility called PropTypes was available as part of the React package, which provided a lot of validators for configuring type definitions for component props. You could access it with React.PropTypes.

However, in later versions of React, this utility has been moved to a separate package called prop-types. To get access to the PropTypes utility, you need to add prop-types as a dependency for your project:

npm install prop-types --save

You can import it into your project files as follows:

import PropTypes from 'prop-types';

To learn more about how you can use prop-types and how it differs from using React.PropTypes and all the available validators, check out the official prop-types documentation.

React PropTypes validators

The PropTypes utility exports a wide range of validators for configuring type definitions. Below, weโ€™ll list the available validators for basic, renderable, instance, multiple, collection, and required prop types.


Over 200k developers use LogRocket to create better digital experiences

๐Ÿ‘ Image
Learn more โ†’

Basic types

Below are the validators for the basic data types:

  • PropTypes.any: The prop can be of any data type
  • PropTypes.bool: The prop should be a Boolean
  • PropTypes.number: The prop should be a number
  • PropTypes.string: The prop should be a string
  • PropTypes.func: The prop should be a function
  • PropTypes.array: The prop should be an array
  • PropTypes.object: The prop should be an object
  • PropTypes.symbol: The prop should be a symbol
Component.propTypes = {
 anyProp: PropTypes.any,
 booleanProp: PropTypes.bool,
 numberProp: PropTypes.number,
 stringProp: PropTypes.string,
 functionProp: PropTypes.func,
 arrayProp: PropTypes.array,
 objectPerop: PropTypes.object,
 symbolProp: PropTypes.symbol,
}

Renderable types

PropTypes also exports the following validators to ensure that React can render the value passed to a prop.

  • PropTypes.node: The prop should be anything that React can render, like a number, string, element, array, or fragment containing these types
  • PropTypes.element: The prop should be a React element
Component.propTypes = {
 nodeProp: PropTypes.node,
 elementProp: PropTypes.element
}

One common use for the PropTypes.element validator is in ensuring that a component has a single child. If the component has no children or multiple children, a warning is displayed on the JavaScript console:

Component.propTypes = {
 children: PropTypes.element.isRequired
}

Instance types

In cases where you require a prop to be an instance of a particular JavaScript class, you can use the PropTypes.instanceOf validator, which leverages the underlying JavaScript instanceof operator:

Component.propTypes = {
 personProp: PropTypes.instanceOf(Person)
}

Multiple types

PropTypes also exports validators that can allow a limited set of values or multiple sets of data types for a prop.

  • PropTypes.oneOf: The prop is limited to a specified set of values, treating it like an enum
  • PropTypes.oneOfType: The prop should be one of a specified set of types, behaving like a union of types
Component.propTypes = {

 enumProp: PropTypes.oneOf([true, false, 0, 'Unknown']),

 unionProp: PropTypes.oneOfType([
 PropType.bool,
 PropType.number,
 PropType.string,
 PropType.instanceOf(Person)
 ])

}

Collection types

In addition to the PropTypes.array and PropTypes.object validators, PropTypes also provides validators for more fine-tuned validation of arrays and objects.

PropTypes.arrayOf

PropTypes.arrayOf ensures that the prop is an array in which all items match the specified type:

Component.propTypes = {

 peopleArrayProp: PropTypes.arrayOf(
 PropTypes.instanceOf(Person)
 ),

 multipleArrayProp: PropTypes.arrayOf(
 PropTypes.oneOfType([
 PropType.number,
 PropType.string
 ])
 )

}

PropTypes.objectOf

PropTypes.objectOf ensures that the prop is an object in which all property values match the specified type:

Component.propTypes = {

 booleanObjectProp: PropTypes.objectOf(
 PropTypes.bool
 ),

 multipleObjectProp: PropTypes.objectOf(
 PropTypes.oneOfType([
 PropType.func,
 PropType.number,
 PropType.string,
 PropType.instanceOf(Person)
 ])
 )

}

PropTypes.shape

When a more detailed validation of an object prop is required, you can use PropTypes.shape. It ensures that the prop is an object that contains a set of specified keys with values of the specified types:

Component.propTypes = {
 profileProp: PropTypes.shape({
 id: PropTypes.number,
 fullname: PropTypes.string,
 gender: PropTypes.oneOf(['M', 'F']),
 birthdate: PropTypes.instanceOf(Date),
 isAuthor: PropTypes.bool
 })
}

PropTypes.exact

For strict or exact object matching, PropTypes.exact will give warnings if extra properties exist in a component:

Component.propTypes = {
 subjectScoreProp: PropTypes.exact({
 subject: PropTypes.oneOf(['Maths', 'Arts', 'Science']),
 score: PropTypes.number
 })
}

Required types

So far, all the PropTypes validators weโ€™ve explored allow for the prop to be optional. However, you can chain isRequired to any prop validator to ensure that a warning is shown whenever the prop is not provided:

Component.propTypes = {

 requiredAnyProp: PropTypes.any.isRequired,
 requiredFunctionProp: PropTypes.func.isRequired,
 requiredSingleElementProp: PropTypes.element.isRequired,
 requiredPersonProp: PropTypes.instanceOf(Person).isRequired,
 requiredEnumProp: PropTypes.oneOf(['Read', 'Write']).isRequired,

 requiredShapeObjectProp: PropTypes.shape({
 title: PropTypes.string.isRequired,
 date: PropTypes.instanceOf(Date).isRequired,
 isRecent: PropTypes.bool
 }).isRequired

}

Custom validators for type checking React props

Usually, you need to define some custom validation logic for component props, for example, to ensure that a prop is passed a valid email address. prop-types allows you to define custom validation functions that you can use for type checking props.

Basic custom validators

The custom validation function takes three arguments:

  • props: An object containing all the props passed to the component
  • propName: The name of the prop to be validated
  • componentName: The name of the component

If the validation fails, it should return an Error object. The error should not be thrown. Additionally, you shouldnโ€™t use console.warn inside the custom validation function:

const isEmail = function(props, propName, componentName) {
 const regex = /^((([^<>()[]\.,;:s@"]+(.[^<>()[]\.,;:s@"]+)*)|(".+"))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,})))?$/;

 if (!regex.test(props[propName])) {
 return new Error(`Invalid prop `${propName}` passed to `${componentName}`. Expected a valid email address.`);
 }
}

Component.propTypes = {
 email: isEmail,
 fullname: PropTypes.string,
 date: PropTypes.instanceOf(Date)
}

๐Ÿ‘ Proptype Failure Notification



You can also use custom validation functions with PropTypes.oneOfType. The example below uses the isEmail custom validation function from the previous code snippet:

Component.propTypes = {
 email: PropTypes.oneOfType([
 isEmail,
 PropTypes.shape({
 address: isEmail
 })
 ])
}

The component will be valid in both of these scenarios:

<Component email="[email protected]" />
<Component email={{ address: '[email protected]' }} />

Custom validators and collections

You can also use custom validation functions with PropTypes.arrayOf and PropTypes.objectOf. When used this way, the custom validation function is called for each key in the array or object.

The custom validation function takes five arguments instead of three:

  • propValue: The array or object itself
  • key: The key of the current item in the iteration
  • componentName: The name of the component
  • location: The location of the validated data, usually prop
  • propFullName: The fully resolved name of the current item being validated. For an array, this will be array[index]; for an object, it will be object.key

Below is a modified version of the isEmail custom validation function for use with collection types:

const isEmail = function(propValue, key, componentName, location, propFullName) {
 const regex = /^((([^<>()[]\.,;:s@"]+(.[^<>()[]\.,;:s@"]+)*)|(".+"))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,})))?$/;

 if (!regex.test(propValue[key])) {
 return new Error(`Invalid prop `${propFullName}` passed to `${componentName}`. Expected a valid email address.`);
 }
}

Component.propTypes = {
 emails: PropTypes.arrayOf(isEmail)
}

All-purpose custom validators

Taking everything weโ€™ve learned about custom validation functions into account, letโ€™s go ahead and create all-purpose custom validators that we can use as standalone validators as well as with collection types.

We can make the isEmail custom validation function an all-purpose validator with just a slight modification. Weโ€™ll add a prop variable that returns either the propFullName or the key. With this, our custom validator can either be used on its own or with collections:

const isEmail = function(propValue, key, componentName, location, propFullName) {
 // Get the resolved prop name based on the validator usage
 const prop = (location && propFullName) ? propFullName : key;

 const regex = /^((([^<>()[]\.,;:s@"]+(.[^<>()[]\.,;:s@"]+)*)|(".+"))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,})))?$/;

 if (!regex.test(propValue[key])) {
 return new Error(`Invalid prop `${prop}` passed to `${componentName}`. Expected a valid email address.`);
 }
}

Component.propTypes = {
 email: PropTypes.oneOfType([
 isEmail,
 PropTypes.shape({
 address: isEmail
 })
 ]),
 emails: PropTypes.arrayOf(isEmail)
}

Validating PercentageStat in React

The following code snippet adds prop types to the PercentageStat component that we reviewed at the beginning of this tutorial:

import React from 'react';
import PropTypes from 'prop-types';

// The PercentageStat component
function PercentageStat({ label, score = 0, total = Math.max(1, score) }) {
 return (
 <div>
 <h6>{ label }</h6>
 <span>{ Math.round(score / total * 100) }%</span>
 </div>
 )
}

// Checks if a value is numeric
// Either a finite number or a numeric string
function isNumeric(value) {
 const regex = /^(\+|-)?((\d*\.?\d+)|(\d+\.?\d*))$/;
 return Number.isFinite(value) || ((typeof value === "string") && regex.test(value));
}


// Checks if value is non-zero
// Value is first converted to a number
function isNonZero(value) {
 return +value !== 0;
}


// Takes test functions as arguments and returns a custom validation function.
// Each function passed in as argument is expected to take a value argument
// expected to accept a value and return a Boolean if it passes the validation.
// All tests must pass for the custom validator to be marked as passed.
function validatedType(...validators) {
 return function(props, propName, componentName) {

 const value = props[propName];

 const valid = validators.every(validator => {
 if (typeof validator === "function") {
 const result = validator(value);
 return (typeof result === "boolean") && result;
 }

 return false;
 });

 if (!valid) {
 return new Error(`Invalid prop \`${propName}\` passed to \`${componentName}\`. Validation failed.`);
 }

 }
}

// Set the propTypes for the component
PercentageStat.propTypes = {
 label: PropTypes.string.isRequired,
 score: validatedType(isNumeric),
 total: validatedType(isNumeric, isNonZero)
}

Conclusion

In this tutorial, weโ€™ve learned how to improve our React components and ensure that they work as expected using prop types. By validating our props with prop types in our development environment, we can prevent errors and bugs from impacting our application once it is deployed.

If you want to learn more about validating component props in React, I recommend checking out the docs.

Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID
  2. Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not server-side

    $ npm i --save logrocket 
    
    // Code:
    
    import LogRocket from 'logrocket'; 
    LogRocket.init('app/id');
     
    // Add to your HTML:
    
    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
     
  3. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • NgRx middleware
    • Vuex plugin
Get started now
๐Ÿ‘ Image
๐Ÿ‘ Image
๐Ÿ‘ Image

Stop guessing about your digital experience with LogRocket

Get started for free

Recent posts:

Debug Next.js apps with AI agents and next-browser

Learn how next-browser gives AI agents runtime context for debugging Next.js apps, including React props, hydration, PPR, forms, and performance.

๐Ÿ‘ Image
Emmanuel John
Jun 17, 2026 โ‹… 9 min read

Stop hardcoding LLM SDKs: Dynamic LLM routing with OpenRouter and Next.js

Build dynamic LLM routing in Next.js with OpenRouter, TanStack AI, task classification, model fallbacks, and cost-aware routing.

๐Ÿ‘ Image
Chizaram Ken
Jun 16, 2026 โ‹… 13 min read

What is TSRX?: What JSX would look like if it were designed today

TSRX adds first-class control flow, conditional hooks, and scoped styles to React via a TypeScript compiler extension โ€” no new framework required.

๐Ÿ‘ Image
Ikeh Akinyemi
Jun 12, 2026 โ‹… 6 min read

How to add authentication to a React Native app with Better Auth

Learn how to build a full React Native auth system using Better Auth and Expo โ€” with email/password login, Google OAuth, session persistence, and protected routes.

๐Ÿ‘ Image
Chinwike Maduabuchi
Jun 9, 2026 โ‹… 13 min read
View all posts

Would you be interested in joining LogRocket's developer community?

Join LogRocketโ€™s Content Advisory Board. Youโ€™ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Sign up now