React: React.Children.onlyChild throws on text child

Created on 17 Feb 2014  路  11Comments  路  Source: facebook/react

Text child is a string so isValidComponent fails. Would it make sense for it to accept a string? Frankly I'm confused by this API...

Core Utilities Wontfix

Most helpful comment

The error message for this is: Invariant Violation: onlyChild must be passed a children with exactly one child. This led me incorrectly down the path of thinking I had passed in multiple children until I dug in and realized it was because I had a string instead of a ReactElement. Could this error message a bit more nuanced for cases such as this?

All 11 comments

I don't understand the use case of this like this either, making it public at this point may be a mistake?

onlyChild is mentionned in https://github.com/facebook/react/issues/751 but is it documented somwhere?

@spicyj @sebmarkbage is this still the case now that we wrapped this?

Nothing here has changed. If you call onlyChild(this.props.children) on a (string) text node, it still isn't a valid ReactElement.

It's not an element. It's a ReactNode. Might be possible to have an isValidNode but I thought we have a propType for that already.

Hey just wanted to mention that I encountered this problem on a wrapper component.

It looks like:

var WithTooltip = React.createClass({
    propTypes: {
        children: React.PropTypes.node.isRequired
    },
    render: function() {
        return React.Children.only(this.props.children);
    }
});
module.exports = WithTooltip;

I can't call <WithTooltip>Some text</WithTooltip> as the method throws an error.

I can't either remove the check since it raises Error: Invariant Violation: WithTooltip.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.

So the solution I found was

    render: function() {
        if (typeof this.props.children === 'string') {
            return <span>{this.props.children}</span>;
        } else {
            return React.Children.only(this.props.children);
        }
    }

Not sure it helps, just wanted to explain my usecase so that you can think of it when taking any action

My understanding was that whatever's in props.children is a child or array of children. Just like <div><span />foo</div> has two children, not one child and one invalid child. If that's agreed upon, how would removing the span result in "foo" no longer being a valid child? We can use React.Children.map in either case without complaint about encountering a non-child.

If nothing else, the name and docs are a bit vague considering how specific the implementation is, and the definition of 'child' is ambiguous. I've never used it, but there's nothing indicating that a string or number isn't a valid value, so I'd assume they were and eventually end up at this issue in a google search while debugging the problem.

The error message for this is: Invariant Violation: onlyChild must be passed a children with exactly one child. This led me incorrectly down the path of thinking I had passed in multiple children until I dug in and realized it was because I had a string instead of a ReactElement. Could this error message a bit more nuanced for cases such as this?

Cool - that's a bit more specific. As a next step, it would be nice to actually detect and message what exactly is invalid for the most common cases.

Was this page helpful?
0 / 5 - 0 ratings