Flow: JSX expressions do not support 'children' prop in body

Created on 2 Feb 2016  路  24Comments  路  Source: facebook/flow

This has to be split in two files because of #1354 :

/*@flow*/

import React from 'react';

export default class TestElement extends React.Component {
  props : {
    attr : string,
    children : any,
  };
}
/*@flow*/

import TestElement from './jsx'

let a = <TestElement attr="a">{"b"}</TestElement>

Reported error:

jsx2.js:5
  5: let a = <TestElement attr="a">{"b"}</TestElement>
             ^^^^^^^^^^^^^^^^^^^^^^ React element `TestElement`
  6:   props : {
               ^ property `children`. Property not found in. See: jsx.js:6
  5: let a = <TestElement attr="a">{"b"}</TestElement>
             ^^^^^^^^^^^^^^^^^^^^^^ type parameter `Props` of React element `TestElement`


Found 1 error

Using Flow 0.21.

The value "b" is going to end up in this.props.children, but Flow doesn't accept this.

I think the type of createElement and respective JSX should be about like this?

declare function createElement<DefaultProps, Props, State, A: $Diff<Props, DefaultProps>, Body>(
  name: ReactClass<DefaultProps, Props, State>,
  attributes: A,
  children?: Body
): ReactElement<DefaultProps, Props, State>;

declare function createElement<DefaultProps, Props, State, A: $Diff<Props, DefaultProps>>(
  name: ReactClass<DefaultProps, Props, State>,
  attributes: A,
  ...children: Array<any>
): ReactElement<DefaultProps, Props, State>;
question react

Most helpful comment

For now I do:

type Props = {
  children?: React.Element<*>,
};

All 24 comments

I think @jeffmo might have more context on this, or maybe even @spicyj?

Is it valid to pass in children as a prop in JSX, like <Foo children={...} />? If so, what happens if I do both, like <Foo children={...}>{...}</Foo>?

How strict should we be? Should we prevent children from being passed (explicitly as prop if allowed and as a child in JSX syntax) if children is not declared in the component's props type?

It seems reasonable to restrict components from internally banging on this.props.children unless the props type explicitly declares the children type, but is that too strict?

Does propTypes provide any precedent here?

Yes, it's valid. JSX children will overwrite the passed prop, if any. The code might clarify:

https://github.com/facebook/react/blob/292f2b7608de5c8b094bc192d64ec01c2a4ccbc5/src/isomorphic/classic/element/ReactElement.js#L114-L171

If you error on other unspecified props, it seems consistent to also give an error if children isn't listed in prop types. The correct type for children React.PropTypes.node.

Any progress here?

Our components tend to look like:

class Foo extends React.Component {
  props: {
    children?: any;  // FIXME flow doesn't typecheck children, see facebook/flow#1355
  };
  render() {
    return <div>{this.props.children}</div>;
  }
}

Does everyone do this or is there a better solution @ 0.22.1?

Alternatively, set children: null in your static defaultProps.

Thanks @samwgoldman! This is a significant one.

Was this actually fixed? Still getting the error, and I cannot set children?: any because then I get "cannot call function with possibly null or undefined value".

return <AutoComponent>{ value }</AutoComponent>; ^^^^^^^^^^^^^^^ React element AutoComponent 45: export default function AutoComponent(props: { children: any }) { ^^^^^^^^^^^^^^^^^ property children. Property not found in. See:

src/js/components/autocomponent/index.jsx:45 75: return <AutoComponent>{ value }</AutoComponent>; ^^^^^^^^^^^^^^^ props of React element AutoComponent

I have the same issue. It looks like this.props.children is too magic for flow.

In that case can we reopen this? @samwgoldman

For now I do:

type Props = {
  children?: React.Element<*>,
};

I am currently experiencing this issue in 0.33.0.

I am currently experiencing this issue in 0.34.0.

Still with 0.37 :(

Considering that @samwgoldman鈥檚 commit addressing this was reverted in https://github.com/facebook/flow/commit/0185892b806c259b07b6d10109cc0faa0b7f3e7a, should this issue be re-opened?

  • 1

I am getting the same error with v0.46.0

All issues are closed but no solution :(

Why was this closed?

can someone please explain why was this issue closed? I'm getting the same thing on 0.57.3, am I doing something wrong?

@jamesisaac thanks, nice read, but the problem still prevails. I must be doing something wrong, but it's still not clear to me what.

I have following component declared:

// @flow
import React, {Component} from 'react';
import type {Node} from 'react';
import * as PropTypes from 'prop-types';

export interface BlockProps {
    className: string;
    id?: string;
    children?: Node; // Node; doesn't work, see https://github.com/facebook/flow/issues/1355
}

export default class Block extends Component<BlockProps> {
    static propTypes = {
        className: PropTypes.string.isRequired,
        id: PropTypes.string,
        children: PropTypes.any
    };

    render() {
        return (<div {...this.props}>{this.props.children}</div>);
    }
}

and then I use it as follows (in render method of another component):

        return (
            <Block className={wrapperClassName}>
                <div>
                </div>
                <div>
                </div>
            </Block>
        );

flow complains that:

329:             <Block className={wrapperClassName}>
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React element `Block`. This type is incompatible with
 12: export default class Block extends Component<BlockProps> {
                                                  ^^^^^^^^^^ BlockProps. See: src/view/components/Block/Block.jsx:12
  Property `children` is incompatible:
      9:     children?: Node; // Node; doesn't work, see https://github.com/facebook/flow/issues/1355
                        ^^^^ null. This type is incompatible with. See: src/view/components/Block/Block.jsx:9
    329:             <Block className={wrapperClassName}>
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React children array`

But as soon as I have only one child within my Block the problem disappears:

        return (
            <Block className={wrapperClassName}>
                <div>
                </div>
            </Block>
        );

But according to docs (https://flow.org/en/docs/react/types/#toc-react-node)

React.Node
This represents any node that can be rendered in a React application. React.Node can be undefined, null, a boolean, a number, a string, a React element, or an array of any of those types recursively.

What am I not getting here?
Thanks in advance!

I'm having the same issue as @mindriven using v0.64.0.

Property `children` is incompatible:
children array
...
This type is incompatible with
union: undefined | null | boolean | number | string | `React.Element` | `React.Portal` | `Iterable`

Is there any particular reason this was closed? (and where's the new issue to track the bug?)
(and what's a reasonable workaround for the meantime?)

Can't reproduce on 0.69

Was this page helpful?
0 / 5 - 0 ratings