Background: I'm trying to specify a prop type for a dimension spec where I can either specify an explicit value, or a min and max value to evaluate. This will be used by an image component that will evaluate if the image is an acceptable height and width for user generated input.
The abstract goal is to have a React props value resolve to one of two possible shapes.
an explicit value for width would have this shape:
{
width: PropTypes.shape({
value: PropTypes.number.isRequired,
error: PropTypes.string
})
}
a min and max value would have this shape:
{
width: PropTypes.shape({
min: {
value: PropTypes.number.isRequired,
error: PropTypes.string
}, max: {
value: PropTypes.number.isRequired,
error: PropTypes.string
}
})
}
EDIT: As pointed out in the accepted answer, there is a bug in this block that I did not catch. For some reason it was not giving me a run-time error, but this is not a working example of nested shapes, see the answer for the correct syntax.
If I try either of these methods and the properties match, everything works as expected so I can safely assume errors are coming from the code below.
I tried using an optionalUnion as seen in the React typechecking documentation via PropTypes.oneOfType with the syntax below.
{
width: PropTypes.oneOfType([
PropTypes.shape({
value: PropTypes.number.isRequired,
error: PropTypes.string
}), PropTypes.shape({
min: {
value: PropTypes.number.isRequired,
error: PropTypes.string
}, max: {
value: PropTypes.number.isRequired,
error: PropTypes.string
}
})
])
}
When I try this, I get the response
Warning: Failed propType: checker is not a function Check the render method of 'MyParentContainer'.
If I use either shape without the PropTypes.oneOfType
method, no complaints in the debugger, everything runs as expected. PropTypes.oneOf
throws a seemingly worse error:
warning.js:45Warning: Failed propType: Invalid prop 'dimensions.width' of value '[object Object]' supplied to 'MyComponent', expected one of [null,null]. Check the render method of 'MyParentContainer'.
Does anyone know if this syntax is off or is this a limitation of PropTypes.oneOfType? Is there a standard solution to this kind of problem?
In this article we will learn how to use React PropType array with shape. We use React PropTypes for type checking of variables in react. It makes debugging much easier and quicker.
propTypes = { //// key is the name of the prop and // value is the PropType } export default Count; PropTypes are also objects with a key and a value pair where the 'key' is the name of the prop while the value represents the type or class by which they are defined.
PropTypes. shape is used when describing an object whose keys are known ahead of time, and may represent different types. const shapeProp = { name: 'Jane', age: 25 } // PropTypes.shape({ name: PropTypes.string, age: PropTypes.number })
Firstly, npm install / yarn add the prop-types package if you haven't already. Then, add your propTypes (and defaultProps too if required) after the stateless functional component has been defined, before you export it.
PropTypes.shape
is not recursive, you have to repeat it for substructures, e.g.
width: PropTypes.shape({
min: PropTypes.shape({
value: PropTypes.number.isRequired,
error: PropTypes.string
}).isRequired,
max: PropTypes.shape({
value: PropTypes.number.isRequired,
error: PropTypes.string
}).isRequired
})
Therefore, the entire validator should be:
const propTypes = {
width: PropTypes.oneOfType([
PropTypes.shape({
value: PropTypes.number.isRequired,
error: PropTypes.string
}),
PropTypes.shape({
min: PropTypes.shape({
value: PropTypes.number.isRequired,
error: PropTypes.string
}).isRequired,
max: PropTypes.shape({
value: PropTypes.number.isRequired,
error: PropTypes.string
}).isRequired
})
])
};
Also, I really recommend to use variables to increase readability and prevent code duplication:
const valueType = PropTypes.shape({
value: PropTypes.number.isRequired,
error: PropTypes.string
});
const propTypes = {
width: PropTypes.oneOfType([
valueType,
PropTypes.shape({
min: valueType.isRequired,
max: valueType.isRequired
})
])
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With