React props - set isRequired on a prop if another prop is null / empty
JavascriptReactjsWai AriaJavascript Problem Overview
I have a component <Button>
.
If the component doesn't has this.props.children
, I want to set the prop ariaLabel
as isRequired
, otherwise in can be optional. How do I do that?
ariaLabel
prop not required:
<Button>Add to bag</Button>
ariaLabel
prop has to be required:
<Button ariaLabel="Add to bag" icon={ favorite } />
if this.props.children
and this.props.ariaLabel
are empty, it throws an error saying that this.props.ariaLabel
is isRequired
<Button icon={ favorite } />
Javascript Solutions
Solution 1 - Javascript
You don't need another library, 'prop-types' provides this out of the box. See https://facebook.github.io/react/docs/typechecking-with-proptypes.html
Example:
import PropTypes from 'prop-types';
//.......
ExampleComponent.propTypes = {
showDelete: PropTypes.bool,
handleDelete: function(props, propName, componentName) {
if ((props['showDelete'] == true && (props[propName] == undefined || typeof(props[propName]) != 'function'))) {
return new Error('Please provide a handleDelete function!');
}
},
}
Solution 2 - Javascript
This may be exactly what you need: https://github.com/thejameskyle/react-required-if
In your case, your propTypes would be:
import requiredIf from 'react-required-if';
Button.propTypes = {
/** icon inside Button. */
icon: React.PropTypes.object,
/** Content inside button */
children: React.PropTypes.node,
/** Aria-label to screen readers */
ariaLabel: requiredIf(React.PropTypes.string, props => !props.children), /*isRequired if children is empty */
};
Solution 3 - Javascript
To add to @chickenchilli's answer above, you could abstract this into a more handy helper function like this:
conditionalPropType.js
export default function conditionalPropType(condition, message) {
if(typeof condition !== 'function') throw "Wrong argument type 'condition' supplied to 'conditionalPropType'";
return function(props, propName, componentName) {
if (condition(props, propName, componentName)) {
return new Error(`Invalid prop '${propName}' '${props[propName]}' supplied to '${componentName}'. ${message}`);
}
}
}
MyComponent.js
import PropTypes from 'prop-types';
import conditionalPropType from './conditionalPropType';
[...]
MyComponent.propTypes = {
conditionProp: PropTypes.bool,
dependentProp: conditionalPropType(props => (props.condition && typeof(props.someProp) !== 'boolean'), "'dependentProp' must be boolean if 'conditionProp' is true"),
};
Solution 4 - Javascript
isRequiredIf
.
Use There is a PR from 4 years ago 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:
ariaLabel: PropTypes.string.isRequiredIf( props => props.children )
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.