Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is React saying "Invalid prop `children`"?

Tags:

reactjs

I'm seeing this error in my console:

Warning: Failed propType: Invalid prop children supplied to ButtonRow. Check the render method of BookingForm.

ButtonRow looks like this:

import React, {Component, PropTypes} from 'react';

export function Left(props) {
    return <div className="left-col">{props.children}</div>;
}

export function Right(props) {
    return <div className="right-col">{props.children}</div>;
}

const LeftOrRight = PropTypes.oneOfType([Left, Right]);

export default class ButtonRow extends Component {
    static propTypes = {
        children: PropTypes.oneOfType([
            PropTypes.arrayOf(LeftOrRight),
            LeftOrRight,
        ]).isRequired,
    };

    render() {
        console.log(this.props.children);
        let children = React.Children.toArray(this.props.children);
        return <div className="row">
            {children.filter(c => c.type === Left)}
            {children.filter(c => c.type === Right)}
        </div>
    }
}

ButtonRow.Left = Left;
ButtonRow.Right = Right;

And I'm rendering it like this:

<ButtonRow>
    <ButtonRow.Left>
        xxx
    </ButtonRow.Left>
    <ButtonRow.Right>
        yyy
    </ButtonRow.Right>
</ButtonRow>

It's displaying exactly as I'd expect. How come it's failing validation? What should I be setting propTypes to?

Ideally I'd like to enforce one of:

  • One Left child
  • One Right child
  • One Left and one Right

Nothing else should be accepted

like image 809
mpen Avatar asked Jun 13 '16 03:06

mpen


2 Answers

This answer is correct https://stackoverflow.com/a/41992473/1426788 but i'd like to share my experience with the same issue.

This error occurred for me when me when my wrapper component was rendering a single child rather than multiple:

For example:

<Foo>
  <Bar>
</Foo> 

would throw a warning where

<Foo>
  <Bar>
  <Baz>
</Foo>

would not.

It appears that rendering a single child in react follows different semantics than rendering multiple children and PropTypes should be updated accordingly.

More info on available PropTypes here: https://facebook.github.io/react/docs/typechecking-with-proptypes.html#proptypes

like image 101
lfender6445 Avatar answered Sep 21 '22 17:09

lfender6445


You can create a custom re-usable prop-type like this:

export function childrenOf(...types) {
    let fieldType = PropTypes.shape({
        type: PropTypes.oneOf(types).isRequired,
    });

    return PropTypes.oneOfType([
        fieldType,
        PropTypes.arrayOf(fieldType),
    ]);
}

And then use it like this:

export default class RadioMenu extends React.Component {

    static propTypes = {
        children: WxTypes.childrenOf(RadioButton).isRequired,
    };

    ...
}
like image 34
mpen Avatar answered Sep 20 '22 17:09

mpen