score:0

Your post asks two questions:

  1. Is there a more clean way to validate whether a prop contains at least one element?
  2. How do you validate the props of objects inside the array?

1: Create a simple validator for the array, apply it in propTypes as normal

Create a validator in your component

const arrayNonEmpty = (props, propName) => {
  const myProp = props[propName];
  if (!Array.isArray(myProp)) return new Error(`${propName} must be an array.`);
  if (myProp.length < 1) return new Error(`${propName} must have at least one element.`);
};

Check whether the prop foo is an array of at least one element

// Use the validator as normal
MyComponent.propTypes = {
  foo: arrayNonEmpty,
};

This is the most simple, clean way to do this. Your code was very close to this but it had a few extra lines that were validating properties of the objects within the array; this code is not needed for the reasons described below.

2: Validating Objects inside the array

I'd suggest validating the properties of objects inside the array within a child component.

If you're passing an array of objects, you'll presumably be representing these objects in your view. Simply add a child component that represents an element of the array, and validate the propTypes of the object passed in to the child component.

Another option is to pass the first object of the array separately from the rest of the array. Then, it could be validated normally as any other prop.

score:2

You could use the PropTypes.checkPropTypes function - you will still need your validator function but the object inside the array can be described via PropTypes:

const myPropShape = {
  bar: PropTypes.string.isRequired,
  baz: PropTypes.number.isRequired,
}

MyComponent.propTypes = {
  foo: function (props, propName, componentName) {
    const val = props[propName]
    if (!Array.isArray(val)) return new Error(`${propName} must be an array`)
    if (val.length === 0) return new Error(`${propName} must have at least one element`)

    val.forEach(elem =>
      PropTypes.checkPropTypes(
        myPropShape,
        elem,
        'prop',
        `${componentName}.${propName}`,
      ),
    )
  }
}


Related Query

More Query from same tag