Search code examples
javascriptreactjstypescript

React Pass Component as props and render it


I am trying to render a React Component passed as props.

export type SummaryCardProps = {
  site?: string;
  title: string;
  description?: string;
  image?: URL;
  imageAlt?: string;
  ContainerElement: Component;
};

export const SummaryCard: FC<SummaryCardProps> = (props) => {
  return (
    <props.ContainerElement>
      <meta name="twitter:card" content="summary" />
      <meta name="twitter:site" content={new URL('https://' + props.site).toString()} />
      <meta name="twitter:title" content={`${props.title}`} />
      <meta name="twitter:description" content="View the album on Flickr." />
      <meta name="twitter:image" content="https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg" />
    </props.ContainerElement>
  );
};

The code is for @peuconomia/react-meta-tags. Now, I am trying to make it generic. I want ContainerElelment to be any ReactComponent to keep it plain and simple. I need it to be for any either a <Head />(Next.js) or <Fragment /> for now.

Possible Answer: Render a react component. However, when I put Component as type, it gives me error.

TS2604: JSX element type 'props.ContainerElement' does not have any construct or call signatures


Solution

  • Solved after changing ContainerType to be type of ComponentType<any>.

    export type SummaryCardProps = {
          site?: string;
          title: string;
          description?: string;
          imageUrl?: URL;
          imageAlt?: string;
          ContainerElement:  ComponentType;
        };
        
        export const SummaryCard: FC<SummaryCardProps> = (props) => {
          return (
            <props.ContainerElement>
              <meta name="twitter:card" content="summary" />
              {props.site && <meta name="twitter:site" content={props.site} />}
              <meta name="twitter:title" content={props.title} />
              {props.description && <meta name="twitter:description" content={props.description} />}
              {props.imageUrl && <meta name="twitter:image" content={props.imageUrl.toString()} />}
              {props.imageAlt && <meta name="twitter:image:alt" content={props.imageAlt.substring(0, 420)} />}
            </props.ContainerElement>
          );
        };