![Creative The name of the picture]()

Clash Royale CLAN TAG#URR8PPP
PropTypes of specific component?
I've got this simple React component:
import {PropTypes} from 'react';
import Column from './Column';
export default function ColumnContainer({children}) {
return (
<div className="cr-column-container">{children}</div>
);
}
let ColumnType = PropTypes.instanceOf(Column);
ColumnContainer.propTypes = {
children: PropTypes.oneOfType([
ColumnType,
PropTypes.arrayOf(ColumnType),
]).isRequired,
};
Which I use like this:
render() {
return (
<ColumnContainer>
<Column>
*snip*
</Column>
</ColumnContainer>
);
}
But it's failing prop-type validation:
Warning: Failed prop type: Invalid prop `children` supplied to `ColumnContainer`.
in ColumnContainer (created by ExampleContainer)
in ExampleContainer
Why is that? I've only used Columns inside of the ColumnContainer. Does PropTypes.instanceOf(Column) not work like I expect? How am I supposed to specify that ColumnContainer will only accept children of type Column?
Column
ColumnContainer
PropTypes.instanceOf(Column)
ColumnContainer
Column
2 Answers
2
Did some digging, came up with this helper function based on josephmartin09's solution:
export function childrenOf(...types) {
let fieldType = PropTypes.shape({
type: PropTypes.oneOf(types),
});
return PropTypes.oneOfType([
fieldType,
PropTypes.arrayOf(fieldType),
]);
}
Usage:
ColumnContainer.propTypes = {
children: childrenOf(Column).isRequired,
};
It's not ideal because it doesn't support native DOM elements like 'div' and the error message is worthless, but it'll do for now.
'div'
I overhauled childrenOf with support for react-hot-loader 4.x:
childrenOf
import { areComponentsEqual } from 'react-hot-loader';
export function childrenOf(...types) {
return requirable((props, propName, componentName, location, propFullName) => {
const component = props[propName];
if(!location) {
location = 'prop';
}
if(!propFullName) {
propFullName = propName;
}
const check = c => types.some(type => areComponentsEqual(type,c.type));
const valid = Array.isArray(component) ? component.every(check) : check(component);
if(!valid) {
return new Error(
`Invalid ${location} `${propFullName}` supplied to `${componentName}`. Every element must be a <${types.map(t => getDisplayName(t)).join('|')}>.`
);
}
return null;
});
}
function requirable(predicate) {
const propType = (props, propName, ...rest) => {
// don't do any validation if empty
if(props[propName] === undefined) {
return null;
}
return predicate(props, propName, ...rest);
};
propType.isRequired = (props, propName, componentName, ...rest) => {
// warn if empty
if(props[propName] === undefined) {
return new Error(`Required prop `${propName}` was not specified in `${componentName}`.`);
}
return predicate(props, propName, componentName, ...rest);
};
return propType;
}
Usage example:
export function TBody({children, ...attrs}) {
return <tbody {...attrs}>{children}</tbody>;
}
TBody.propTypes = {
children: WxTypes.childrenOf(TRow),
};
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
check this out: github.com/facebook/react/issues/2979
– james emanon
Sep 12 '16 at 19:30