I need to validate dictionary-like objects in my reducers, but since I'm already using Babel I don't want to resort to tools like Typescript.
Take this object as an example:
posts : {
byId : {
"post1" : {
id : "post1",
author : "user1",
body : "......",
comments : ["comment1", "comment2"]
},
"post2" : {
id : "post2",
author : "user2",
body : "......",
comments : ["comment3", "comment4", "comment5"]
}
}
allIds : ["post1", "post2"]
}
How could I express my expectations for the byId object using PropTypes? Is it possible? If so, how?
You can write custom proptype checkers if you can't achieve what you wan't with PropTypes
' builtin proptypes.
If you want an all the values of the byId
to be objects with the properties id
, author
, body
and comments
, you can use shape
, objectOf
, and arrayOf
. If you want allIds
to include all the keys of byId
you can write a custom validator:
posts: PropTypes.shape({
byId: PropTypes.objectOf(PropTypes.shape({
id: PropTypes.string,
author: PropTypes.string,
body: PropTypes.string,
comments: PropTypes.arrayOf(PropTypes.string)
})),
allIds(props, propName, componentName) {
if(!Object.keys(props.byId).every(postID => props[propName].includes(postID))) {
return new Error('allIds must include all the ids provided to byId!');
}
}
})
The above uses shape so it expects a posts
object with the keys byId
and allIds
. It expects byId
to be an object with the property values to also be object of a shape, with id
, author
and body
being strings, with comments
being an array of strings. Finally, it uses a custom proptype validator that checks if every key in byId
(the post IDs) exists in allIds
. If not, then throw an error. Beware though, this won't cover the case that allIds
has post IDs that don't exist in byIds
. See How to know if two arrays have the same values for more solutions. You can add isRequired
where necessary.
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