score:61

Accepted answer

Try Component instead of component. React requires an upperCase for jsx tag:

renderCards(Component){
  let cards =  this.props.list.map(function(cardData){
     return <Component data={cardData}/>
   })
  return cards
}

score:0

You can use React.createElment(myLowerCasedComponent) - I was working through a tutorial in Javascript and porting on the fly to TypeScript. In TypeScript I got it working like this:

    // PrivateRoute.tsx
    type PropType = {
        component: React.ComponentType
    } & RouteProps
    
    // Component that wraps another component to produce a
    // component which only renders if the user is logged in. If not logged
    // in then the browser is redirected to the signin component.
    const PrivateRoute: React.FC<PropType> = ({ component, ...rest }) => {
        return (
            <Route
                {...rest}
                render={(props) =>
                    isAuth() ? (
                        React.createElement(component)
                    ) : (
                        <Redirect
                            to={{
                                pathname: '/signin',
                                state: { from: props.location }
                            }}
                        />
                    )
                }
            ></Route>
        )
    }
    
    export default PrivateRoute

That meant I could call my wrapper like this:

    class Routes extends React.Component {
        render(): React.ReactElement {
            return (
                <BrowserRouter>
                    <Switch>
                        <Route path="/signin" exact component={Signin} />
                        <Route path="/auth/activate/:token" exact component={Activate} />
                        <AdminRoute path="/admin" exact component={Admin} />
                        { /* here my param name is 'component' matching than
                             the other routes. Not 'Component=Private' (ugh) */ }
                        <PrivateRoute path="/private" exact component={Private} />
                    </Switch>
                </BrowserRouter>
            )
        }
    }
    
    export default Routes

Here my Private component is a standard React class based component:

}

type ChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => void

class Private extends React.Component<PropType, StateType> {
    render(): JSX.Element {
        return (
            <Layout>
                <div className="col-md-6 offset-md-3">
                { /* stuff here... */ }
                </div>
            </Layout>
        )
    }
}

score:4

Thanks to Damien's answer, here's the same answer using TypeScript with React.

Instead of this, i.e. a simple component without a wrapper ...

export const SiteMapContent: FunctionComponent = () => {
  return (
    <React.Fragment>
      <h1>Site Map</h1>
      <p>This will display the site map.</p>
    </React.Fragment>
  );
}

... you can pass a component into a wrapper to be rendered there, like this ...

const renderContent: FunctionComponent<FunctionComponent> = (Foo: FunctionComponent) => {
  return (
    <div className="foo">
      <Foo />
    </div>
  )
}

export const SiteMap: FunctionComponent = () => {
  return renderContentOne(SiteMapContent);
}

const SiteMapContent: FunctionComponent = () => {
  return (
    <React.Fragment>
      <h1>Site Map</h1>
      <p>This will display the site map.</p>
    </React.Fragment>
  );
}

Again the name of the parameter must be upper-case e.g. Foo not foo.

A different way of course, instead of passing a component as asked in the OP is to pass an element instead of a component (in which case the parameter name needn't be upper-case):

const renderContent: FunctionComponent<ReactElement> = (foo: ReactElement) => {
  return (
    <div className="foo">
      {foo}
    </div>
  )
}

export const SiteMap: FunctionComponent = () => {
  const foo: ReactElement = <SiteMapContent />;
  return renderContentOne(foo);
}

const SiteMapContent: FunctionComponent = () => {
  return (
    <React.Fragment>
      <h1>Site Map</h1>
      <p>This will display the site map.</p>
    </React.Fragment>
  );
}

Related Query

More Query from same tag