I have a React component that gets a configuration object as a prop, it looks something like this:
{
active: true,
foo: {
bar: 'baz'
}
}
In some cases, I want to disable the feature that the component displays by passing in a different object with active: false
, like this:
{
active: false
}
This works fine and is not the problem.
However, I also want to make sure that client code that uses my component supplies the proper configuration object:
How do I define prop types for a case like this?
I've tried:
MyComponent.propTypes = {
config: PropTypes.oneOf([
{
active: false
},
PropTypes.shape({
active: true,
foo: PropTypes.shape({
bar: PropTypes.string.isRequired
})
}).isRequired
]).isRequired
};
But this gives me the following warning:
Warning: Failed prop type: Invalid prop
config
of value[object Object]
supplied toMyComponent
, expected one of [{"active":true},null].in MyComponent
I know why this does not work: it's because PropTypes.oneOf
does not expect dynamic prop type matchers as values, but simply an array of valid arguments.
The question is, is there a way to make this work?
I've made a runnable sandbox example where you can try out the example code above: https://codesandbox.io/s/n9o0wl5zlj
As wgcrouch
suggested in his answer, the prop-types
lib does not provide this functionality, so using a custom prop type is the way to go.
Fortunately, as Tom Fenech pointed out in the comments to my question, this particular problem has already been solved, so there is an npm package available that I've used: react-required-if.
My working solution looks like this:
import React from 'react';
import PropTypes from 'prop-types';
import requiredIf from 'react-required-if';
function MyComponent({ config }) {
if (!config.active) {
return null;
}
return <h1>Hello {config.foo.bar}!</h1>;
}
MyComponent.propTypes = {
config: PropTypes.shape({
active: PropTypes.bool.isRequired,
foo: requiredIf(
PropTypes.shape({
bar: PropTypes.string.isRequired
}),
props => props.active
)
})
};
export default MyComponent;
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments