Is there a way to have multiple validations on a single prop using React.PropTypes
. specifically want to blend a custom validation and a stock validation.
I have two props, an object options
, and a string value
. i want to check that props.value
is a string but also a key on the object. using coffeescript this looks like:
propTypes:
options: React.PropTypes.Object.isRequired
value: (props, propName, ponentName) ->
unless props[propName] of props.options
new Error('my custom message')
this works great, but i also want to ensure that my value is a string type. I'm sure i can manually stick in that validation in the custom function no problem, but ideally, i'd just like to use React.PropTypes.string.isRequired
. ive tried just putting it in the custom function and executing it but that did not work. the following didn't work either:
value: React.PropTypes.string.isRequired && (props, propName, ponentName) ->
unless props[propName] of props.options
new Error('my custom message')
is there a way to get this working using reacts built in validator, or is rewriting it in my function the only option?
Is there a way to have multiple validations on a single prop using React.PropTypes
. specifically want to blend a custom validation and a stock validation.
I have two props, an object options
, and a string value
. i want to check that props.value
is a string but also a key on the object. using coffeescript this looks like:
propTypes:
options: React.PropTypes.Object.isRequired
value: (props, propName, ponentName) ->
unless props[propName] of props.options
new Error('my custom message')
this works great, but i also want to ensure that my value is a string type. I'm sure i can manually stick in that validation in the custom function no problem, but ideally, i'd just like to use React.PropTypes.string.isRequired
. ive tried just putting it in the custom function and executing it but that did not work. the following didn't work either:
value: React.PropTypes.string.isRequired && (props, propName, ponentName) ->
unless props[propName] of props.options
new Error('my custom message')
is there a way to get this working using reacts built in validator, or is rewriting it in my function the only option?
Share Improve this question edited Nov 15, 2016 at 0:01 machineghost 35.7k32 gold badges173 silver badges260 bronze badges asked Jul 1, 2015 at 16:18 PhilVargPhilVarg 4,8203 gold badges22 silver badges38 bronze badges2 Answers
Reset to default 3From the Reusable Components page in the docs:
You can also specify a custom validator. It should return an Error
// object if the validation fails. Don't `console.warn` or throw, as this
// won't work inside `oneOfType`.
customProp: function(props, propName, ponentName) {
if (!/matchme/.test(props[propName])) {
return new Error('Validation failed!');
}
}
So a propType returns nothing or an error object. We can write a 'all' function which takes two propTypes and merges the result.
const allPropTypes = (...types) => (...args) => {
const errors = types.map((type) => type(...args)).filter(Boolean);
// no errors? cool!
if (errors.length === 0) return;
// collect the messages and join them together
const message = errors.map((e) => e.message).join('\n');
return new Error(message);
};
Then you can use this to assert against multiple propTypes.
propTypes = {
foo: allPropTypes(
PropTypes.string.isRequired,
(props, propName, ponentName) => props.options && props.options[props[propName]]
? undefined
: new Error(
`${ponentName}: expected prop ${propName}="${prop[propName]}"`
+ `to be a key of prop "options" `
+ `(one of ${Object.keys(props.options).join(', ')})`
)
)
}
Note: none of this is tested, but no syntax errors! You can pile it to es3 with babel, or convert it to CS by hand.
If you follow this link, Ian Thomas explains the use of a createChainableTypeChecker method which is in react but not exported as part of propTypes module. The article has a clear explanation of how you can use the same code to chain validation calls:
function createChainableTypeChecker(validate) {
function checkType(isRequired, props, propName, ponentName, location) {
ponentName = ponentName || ANONYMOUS;
if (props[propName] == null) {
var locationName = ReactPropTypeLocationNames[location];
if (isRequired) {
return new Error(
("Required " + locationName + " `" + propName + "` was not specified in ") +
("`" + ponentName + "`.")
);
}
return null;
} else {
return validate(props, propName, ponentName, location);
}
}
var chainedCheckType = checkType.bind(null, false);
chainedCheckType.isRequired = checkType.bind(null, true);
return chainedCheckType;
}