Is it possible to use React.PropTypes
to enforce length\'s on an array?
Here is a very simple case:
const TWO_NUMBERS = PropTypes.array; // i
in this case you would need to write your own special PropTypes function which react provides you to do.
const TWO_NUMBERS = function(props, propName, componentName) {
if (!Array.isArray(props.TWO_NUMBERS) || props.TWO_NUMBERS.length != 2 || !props.TWO_NUMBERS.every(Number.isInteger)) {
return new Error(`${propName} needs to be an array of two numbers`);
}
return null
}
This would throw an error if TWO_NUMBERS isn't an array, isn't an array of two, and isn't an array of only integers.
you can get information about proptype functions here:
https://facebook.github.io/react/docs/typechecking-with-proptypes.html#react.proptypes
its at the bottom of that example block.
A custom function would be the correct approach here.
const propTypes = {
TWO_NUMBERS: arrayOfLength.bind(null, 2)
}
const arrayOfLength = (expectedLength, props, propName, componentName) => {
const arrayPropLength = props[propName].length
if (arrayPropLength !== expectedLength) {
return new Error(
`Invalid array length ${arrayPropLength} (expected ${expectedLength}) for prop ${propName} supplied to ${componentName}. Validation failed.`
)
}
}
Inspired by the answer of @finalfreq, I came up with this. It handles two numbers (floats in this case) and can also be used as arrayOf(twoNumbers)
. Not sure how to make it work like twoNumbers.isRequired
yet...
Also I think the code is cleaner and easier to follow if you don't use the negation in the validation comparison.
import invariant from 'invariant';
function isValid(value) {
return Array.isArray(value) && value.length === 2 && value.every(Number.isFinite);
}
export default function twoNumbers(props, propName, componentName) {
if (Array.isArray(props)) {
props.forEach((item, index) => {
invariant(
isValid(item),
`Array item index ${index} is ${item}, but needs to be an array of two numbers`
);
});
}
const value = props[propName];
if (!value) return; // not required so could be null
invariant(isValid(value), `${componentName} ${propName} needs to be an array of two numbers`);
}
PropTypes
checks for types not for attributes. Also, checking for PropTypes
is disabled in production mode. That makes it impossible for PropTypes
to check for ever changing array lengths during run-time.