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