In a React component, using PropTypes.instanceOf(Class) with mobx is really nice, because it means you don't have to manually construct a shape to check against.
With mobx-state-tree, you can't use instanceOf because the store is an object not a class, so if we want some deeper check than just observableObject, we have to pass a manually constructed shape through.
Is there any thought around supplying a function that can check to see if the prop is the correct type in state-tree? From a brief look, a barbaric approach could check if the store name is equal to the props $treenode.type.name.
I'd like to try and avoid manually writing shapes if possible, any ideas?
You can use the following that should work:
function modelOf(type){
return (props, propName, componentName) => {
if(!isStateTreeNode(props[propName]) || !type.is(props[propName])){
return new Error("Invalid value for prop " + propName)
}
}
}
MyComponent.propTypes = {
todo: modelOf(Todo)
}
Let me know! :)
EDIT: Returned new Error instead of throw
Awesome, that worked a treat! Thanks!
n.b. probably you want to check also isMstNode(thing) as type.is will
also accept a snapshot in the correct shape, that might be useless for the
component. @Mattia, maybe add this to the tips section in the bottom?
Op wo 6 sep. 2017 om 08:21 schreef James Coleman notifications@github.com:
Awesome, that worked a treat! Thanks!
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/mobxjs/mobx-state-tree/issues/365#issuecomment-327386563,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABvGhNmHOU0v7mfpjWT3CeSr3_XGXoYjks5sfjnRgaJpZM4PN4qo
.
Uh, good catch @mweststrate ! Updated the commend!
Will add it to readme tips! :)
Updated the commend!
@mattiamanzati I don't completely follow.
is !isStateTreeNode(props[propName]) what @mweststrate means by isMstNode(thing) ?
Thanks!
Yeah, it got changed between versions :)
And about .isRequired ?
I tried and is not working..
const Project = types.model('Project', {
_id: types.string,
});
function modelOf(type) {
return (props, propName) => {
if (isStateTreeNode(props[propName]) && type.is(props[propName])) {
return true;
}
return new Error(`Invalid value for prop ${propName}`);
};
}
And in my component..
project: modelOf(Project).isRequired,
But I get..
Failed prop type: ProjectCard: prop type
projectis invalid; it must be a function, usually from theprop-typespackage, but receivedundefined.
function modelOf(type) {
const fn = (props, propName) => {
if (isStateTreeNode(props[propName]) && type.is(props[propName])) {
return true
}
return new Error(`Invalid value for prop ${propName}`)
}
fn.isRequired = (props, propName) => !(propName in props) ? new Error(`Missing prop ${propName} in props`) : fn(props, propName)
return fn
}
quick update to support isRequired :)
Using @mattiamanzati latest function I got the following error:
Warning: Node: type specification of prop `node` is invalid; the type checker function must return `null` or an `Error` but returned a boolean. You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).
checkPropTypes.js:19
It seems React has changed how prop type validators work, and now you must return null, so I changed the function to:
import { isStateTreeNode } from 'mobx-state-tree';
export default function modelOf(type) {
const fn = (props, propName) => {
if (isStateTreeNode(props[propName]) && type.is(props[propName])) {
return null;
}
return new Error(`Invalid value for prop ${propName}`)
}
fn.isRequired = (props, propName) => !(propName in props) ? new Error(`Missing prop ${propName} in props`) : fn(props, propName);
return fn;
}
And it seems to work.
I propose adding this to the readme or to the docs somewhere?
It'd be great if this could be added to one of the mobx npm packages. But not sure which one 😄
I think until a decision is made, just making a note in the readme, pointing to this issue (or inlining the function there) would be a great start, I had trouble finding this issue through google.
Sorry to open this after two years, but wanted to confirm something. My understanding is that by default PropTypes are not required (as in that prop doesn't need to be passed), but also allow null values unless isRequired is specified. So would this make more sense instead?
export default function mstModelOf(type: any) {
const fn = (props: any, propName: string) => {
if (props[propName] == null) {
return null
}
if (isStateTreeNode(props[propName]) && type.is(props[propName])) {
return null
}
return new Error(`Invalid value for prop ${propName}`)
}
fn.isRequired = (props: any, propName: string) => {
if (!(propName in props)) {
return new Error(`Missing prop ${propName} in props`)
}
if (props[propName] === null) {
return new Error(`Prop ${propName} in props has invalid null value`)
}
return fn(props, propName)
}
return fn
}
Most helpful comment
It'd be great if this could be added to one of the mobx npm packages. But not sure which one 😄