React proptype array with shape

ArraysReactjsReact Proptypes

Arrays Problem Overview


Is there a built-in way to use proptypes to ensure that an array of objects being passed to a component is actually an array of objects of a specific shape?

Maybe something like this?

annotationRanges: PropTypes.array(PropTypes.shape({
    start: PropTypes.number.isRequired,
    end: PropTypes.number.isRequired,
})),

Am I missing something super obvious here? Seems like this would be highly sought after.

Arrays Solutions


Solution 1 - Arrays

You can use React.PropTypes.shape() as an argument to React.PropTypes.arrayOf():

// an array of a particular shape.
ReactComponent.propTypes = {
   arrayWithShape: React.PropTypes.arrayOf(React.PropTypes.shape({
     color: React.PropTypes.string.isRequired,
     fontSize: React.PropTypes.number.isRequired,
   })).isRequired,
}

See the Prop Validation section of the documentation.

UPDATE

As of react v15.5, using React.PropTypes is deprecated and the standalone package prop-types should be used instead :

// an array of a particular shape.
import PropTypes from 'prop-types'; // ES6 
var PropTypes = require('prop-types'); // ES5 with npm
ReactComponent.propTypes = {
   arrayWithShape: PropTypes.arrayOf(PropTypes.shape({
     color: PropTypes.string.isRequired,
     fontSize: PropTypes.number.isRequired,
   })).isRequired,
}

Solution 2 - Arrays

Yes, you need to use PropTypes.arrayOf instead of PropTypes.array in the code, you can do something like this:

import PropTypes from 'prop-types';

MyComponent.propTypes = {
  annotationRanges: PropTypes.arrayOf(
    PropTypes.shape({
      start: PropTypes.string.isRequired,
      end: PropTypes.number.isRequired
    }).isRequired
  ).isRequired
}

Also for more details about proptypes, visit Typechecking With PropTypes here

Solution 3 - Arrays

And there it is... right under my nose:

From the react docs themselves: https://facebook.github.io/react/docs/reusable-components.html

// An array of a certain type
    optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),

Solution 4 - Arrays

There's a ES6 shorthand import, you can reference. More readable and easy to type.

import React, { Component } from 'react';
import { arrayOf, shape, number } from 'prop-types';

class ExampleComponent extends Component {
  static propTypes = {
    annotationRanges: arrayOf(shape({
      start: number,
      end: number,
    })).isRequired,
  }

  static defaultProps = {
     annotationRanges: [],
  }
}

Solution 5 - Arrays

If I am to define the same proptypes for a particular shape multiple times, I like abstract it out to a proptypes file so that if the shape of the object changes, I only have to change the code in one place. It helps dry up the codebase a bit.

Example:

// Inside my proptypes.js file
import PT from 'prop-types';

export const product = {
  id: PT.number.isRequired,
  title: PT.string.isRequired,
  sku: PT.string.isRequired,
  description: PT.string.isRequired,
};


// Inside my component file
import PT from 'prop-types';
import { product } from './proptypes;


List.propTypes = {
  productList: PT.arrayOf(product)
}

Solution 6 - Arrays

This was my solution to protect against an empty array as well:

import React, { Component } from 'react';
import { arrayOf, shape, string, number } from 'prop-types';

ReactComponent.propTypes = {
  arrayWithShape: (props, propName, componentName) => {
    const arrayWithShape = props[propName]
    PropTypes.checkPropTypes({ arrayWithShape:
        arrayOf(
          shape({
            color: string.isRequired,
            fontSize: number.isRequired,
          }).isRequired
      ).isRequired
    }, {arrayWithShape}, 'prop', componentName);
    if(arrayWithShape.length < 1){
      return new Error(`${propName} is empty`)
    }
  }
}

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
QuestiontnrichView Question on Stackoverflow
Solution 1 - ArraysPierre CriulanscyView Answer on Stackoverflow
Solution 2 - ArraysAlirezaView Answer on Stackoverflow
Solution 3 - ArraystnrichView Answer on Stackoverflow
Solution 4 - ArraysMoewizView Answer on Stackoverflow
Solution 5 - ArraysYo WakitaView Answer on Stackoverflow
Solution 6 - ArrayssdcView Answer on Stackoverflow