How do you validate the PropTypes of a nested object in ReactJS?

Reactjs

Reactjs Problem Overview


I'm using a data object as my props for a component in ReactJS.

<Field data={data} />

I know its easy to validate the PropTypes object itself:

propTypes: {
  data: React.PropTypes.object
}

But what if I want to validate the values inside? ie. data.id, data.title?

props[propName]: React.PropTypes.number.required // etc...

Reactjs Solutions


Solution 1 - Reactjs

You can use React.PropTypes.shape to validate properties:

propTypes: {
    data: React.PropTypes.shape({
      id: React.PropTypes.number.isRequired,
      title: React.PropTypes.string
    })
}

Update

As @Chris pointed out in comments, as of React version 15.5.0 React.PropTypes has moved to package prop-types.

import PropTypes from 'prop-types';    

propTypes: {
    data: PropTypes.shape({
      id: PropTypes.number.isRequired,
      title: PropTypes.string
    })
}

More info

Solution 2 - Reactjs

If React.PropTypes.shape doesn't give you the level of type checking you want, have a look at tcomb-react.

It provides a toPropTypes() function which lets you validate a schema defined with the tcomb library by making use of React's support for defining custom propTypes validators, running validations using tcomb-validation.

Basic example from its docs:

// define the component props
var MyProps = struct({
  foo: Num,
  bar: subtype(Str, function (s) { return s.length <= 3; }, 'Bar')
});

// a simple component
var MyComponent = React.createClass({

  propTypes: toPropTypes(MyProps), // <--- !

  render: function () {
    return (
      <div>
        <div>Foo is: {this.props.foo}</div>
        <div>Bar is: {this.props.bar}</div>
      </div>
    );
  }    
});

Solution 3 - Reactjs

Wanted to note that nesting works beyond one level deep. This was useful for me when validating URL params:

propTypes = {
  match: PropTypes.shape({
    params: PropTypes.shape({
      id: PropTypes.string.isRequired
    })
  })
};

Solution 4 - Reactjs

user: React.PropTypes.shap({
    age: (props, propName) => {
       if (!props[propName] > 0 && props[propName] > 100) {
          return new Error(`${propName} must be betwen 1 and 99`)
       }
       return null
    },
})

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdamView Question on Stackoverflow
Solution 1 - ReactjsnilgunView Answer on Stackoverflow
Solution 2 - ReactjsJonny BuchananView Answer on Stackoverflow
Solution 3 - ReactjsdatchungView Answer on Stackoverflow
Solution 4 - ReactjsMostafa EzzView Answer on Stackoverflow