9
votes

The React team announced that since React 16:

You can now return an array of elements from a component’s render method.

This works in typescript for regular class components, but I cannot get it to work for stateless functional components.

See this repo if you want to reproduce for yourself.

Code:

import * as React from 'react';

// See this example working in a non-TS environment: https://codesandbox.io/s/ppl3wopo8j
class Hello extends React.Component {
    render() {
        return <div>
        <Foo />
        <Bar /> {/* Error: 'JSX element type 'Element[]' is not a constructor function for JSX elements. */}
      </div>;
    }
}

class Foo extends React.Component {
    render() {
        return [<div>foo</div>, <div>fooz</div>];
    }
}

function Bar() {
    // Cannot render an array from a SFC
    return [<div>bar</div>, <div>baz</div>];
}

Building this snipper results in the following error:

'JSX element type 'Element[]' is not a constructor function for JSX elements.
  Property 'render' is missing in type 'Element[]'.'

As you can see, rendering an array from a regular class component works, but it fails when rendering an array from a stateless functional component.

I'm unsure whether the problem lies with my code/setup, the DefinitelyTyped react types, or with typescript itself.

3

3 Answers

3
votes

Until the open Definitely Typed issue has been resolved, the best work around is probably just to use <React.Fragment/> instead. For functional purposes, I don't think there is any difference:

const Bar: React.SFC<CheckoutProps> = (props) => {
  return (
    <React.Fragment>
      <div>bar</div>
      <div>baz</div>
    </React.Fragment>
  );
};
-3
votes

You can suppress the error and have your code working by casting your component as any:

const Bar: any = () => [<div>bar</div>, <div>baz</div>]
-3
votes

"You can now return an array of elements from a component’s render method."

The array of JSX is being compiled by React.Components render method. A stateless functional component lacks that render method.

You could either wrap your array of elements in a parent div instead of the array or use a regular class component.