Conditional React PropTypes

Viewed 3720

I have a React component which I would like to enforce one of two props to be provided - if neither is provided I'd like to be able to trigger a PropType warning:

MyComponent.propTypes = {
  firstProp: PropTypes.string.isRequired, // required only if `otherProp` not provided
  otherProp: PropTypes.string.isRequired, // required only if `firstProp` not provided
}

I believe this is possible with AirBnB's prop-types but I'm wondering if this can be done with only React PropTypes.

2 Answers

There is an npm for everything. Here is one for conditional prop types based on props. Here is an example of how I used it in a project for determining ad size prop types.

import React, { Component } from 'react';
import isRequiredIf from 'react-proptype-conditional-require';
import PropTypes from 'prop-types';

class AdSlot extends Component {
  // React component stuff
}

const slotPropTypes = PropTypes.oneOfType([
  PropTypes.string, // e.g. 'fluid'
  PropTypes.arrayOf(PropTypes.number), // e.g. [300, 250]
  PropTypes.arrayOf(PropTypes.array), // e.g. [[300, 250], [1650, 300]]
  PropTypes.arrayOf(PropTypes.oneOfType([ // e.g. ['fluid', [300, 250]]
    PropTypes.string.isRequired,
    PropTypes.array,
  ])),
]);

const responsiveSizesPropTypes = PropTypes.arrayOf(PropTypes.oneOfType([
  PropTypes.number,
  PropTypes.array,
  PropTypes.string,
]));

const doesNotHaveResponsiveSizes = props => !(props.hasOwnProperty('responsiveSizes'));
const doesNotHaveSlotSizes = props => !(props.hasOwnProperty('slotSizes'));

AdSlot.proptypes = {
  slotSizes: isRequiredIf(slotPropTypes, doesNotHaveResponsiveSizes),
  responsiveSizes: isRequiredIf(responsiveSizesPropTypes, doesNotHaveSlotSizes),
}

export default AdSlot;

Use isRequiredIf.

There is a PR from 4 years ago by @evcohen that added isRequiredIf to the PropTypes library. Unfortunately, even at that time they were putting the PropTypes library in maintenance mode and would not merge it in.

The company I work for still uses PropTypes and so we forked the master branch of the PropTypes library and added this functionality in.

So now you can do something like this:

MyComponent.propTypes = {
  firstProp: PropTypes.string.isRequiredIf( props => !props.otherProp ), // required only if `otherProp` not provided
  otherProp: PropTypes.string.isRequiredIf( props => !props.firstProp ), // required only if `firstProp` not provided
}

Super clean and minimal.

Feel free to use our fork in your own project by updating your package.json with the following:

"prop-types": "github:cntral/prop-types#isRequiredIf"

NOTE: It does not take a boolean param, only a function that is passed the props and needs to return a boolean.

Related