Reputation: 2026
I'm writing a small Toolbar
component in React. Here's how it should be used:
<Toolbar>
<ToolbarButtonSearch />
<ToolbarButtonFold />
</Toolbar>
or
<Toolbar>
<ToolbarButtonSearch />
</Toolbar>
or
<Toolbar>
<ToolbarButtonFold />
</Toolbar>
I'd like to be able to specify that the only children Toolbar
accepts are one of ToolbarButtonSearch
, one of ToolbarButtonFold
, or one of each.
Here's what I have now (not including imports):
export default class Toolbar extends React.Component {
static get propTypes() {
const acceptedChildren =
React.PropTypes.oneOfType([
React.PropTypes.instanceOf(ToolbarButtonFold),
React.PropTypes.instanceOf(ToolbarButtonSearch)
]);
return {
children: React.PropTypes.oneOfType([
React.PropTypes.arrayOf(acceptedChildren),
acceptedChildren
]).isRequired
};
}
render() {
return (
<div className="toolbar">
{this.props.children}
</div>
);
}
}
Here's how I'm using it:
<Toolbar>
<ToolbarButtonFold />
</Toolbar>
This results in the following error:
Warning: Failed prop type: Invalid prop 'children' supplied to 'Toolbar'.
I'm not sure what I'm doing wrong. Any insight would be very helpful. Thanks!
Upvotes: 0
Views: 648
Reputation: 9185
Did you tried to do:
customProp: function (props, propName, componentName) {
props.children.forEach(child => {
if (!child instanceof ToolbarButtonSearch && !child instanceof ToolbarButtonFold) {
return new Error(
'Invalid children supplied to' +
' `' + componentName + '`. Validation failed.'
)
}
})
}
Upvotes: 1
Reputation: 226
Instead of passing components (since they have to be imported into Toolbar, anyway), you could just pass props defining if the specific component should be displayed.
const Toolbar = ({showButtonSearch = false, showButtonFold = false, buttonSearchProps = {}, buttonFoldProps = {}}) => {
return (
<div className='Toolbar'>
{showButtonSearch ? <ButtonSearch {...buttonSearchProps} /> : null}
{showButtonFold ? <ButtonFold {...buttonFoldProps} /> : null}
</div>
)
}
This method would also allow you to pass props for the children as well as any further functionality you need before displaying the children (such as ordering the children a specific way).
Upvotes: 1