Home > other >  Dynamically render string as html component in TypeScript
Dynamically render string as html component in TypeScript

Time:12-01

How can I type a prop that accepts ComponentType or a string?

Suppose the following code.

interface MyComponentProps {
    Component: React.ComponentType
}
const MyComponent: React.FC<PropsWithChildren<MyComponentProps>> = ({Component}) => {
    return <Component>{children}</Component>
}
<MyComponent
    Component="span"
/>

Trying this in TS gives the following error.

Type 'string' is not assignable to type 'ComponentType<{}> | undefined'.

How can I dynamically render a native html tag using JSX?

CodePudding user response:

In terms of react and javascript, your code is correct. The issue here is the types. The string "span" is not a ComponentType. The type you want for Component is React.ElementType. If you check out the definition of ElementType it includes all of the intrinsic jsx elements or a component type.

You can come to this conclusion by yourself by rendering a <span></span> and hovering over or clicking through to the span keyword. You'll see the type is JSX.IntrinsicElements.span. If you click through you can see that IntrinsicElements includes all the html elements. I did a search to see where that type was being used which led me to the React.ElementType

Updated code:

interface MyComponentProps {
    Component: React.ElementType
}
const MyComponent: React.FC<PropsWithChildren<MyComponentProps>> = ({Component}) => {
    return <Component>{children}</Component>
}
<MyComponent
    Component="span"
/>

Side note: React.FC might not be the best approach anymore. Instead it seems to be preferable to just assign a type to the props directly:

const MyComponent = ({Component}: PropsWithChildren<MyComponentProps>) => {
    return <Component>{children}</Component>
}

More on that here if you're interested: https://github.com/facebook/create-react-app/pull/8177

  • Related