I have a function component MyComponent
and I'm trying to set a default prop for component
so that if not supplied, the root node will render as a "span". But I'm getting the following error:
TS2604: JSX element type 'Component' does not have any construct or call signatures.
interface IMyComponentProps {
component?: React.ElementType<React.HTMLAttributes<HTMLElement>>;
}
const MyComponent: React.FunctionComponent<IMyComponentProps> = ({
className,
component: Component, <-- complaining
...other
}) => (
<Component className={className}
{...other}
/>
);
MyComponent.defaultProps = {
component: 'span'
};
MyComponent.displayName = 'MyComponent';
export default MyComponent;
My comment was incorrect. Try using React.ComponentType
as the type for your input component.
interface IMyComponentProps {
Component: React.ComponentType;
}
const MyComponent: React.FunctionComponent<IMyComponentProps> = ({Component, ...other}) => {
return (<Component {...other} />)
};
This would need to be used like so:
const Span = () => <span>Hey</span>
...
<MyComponent Component={Span}/>
However, this still leaves the issue of setting the default prop as a string. You'd need to set the default prop to be a React component which returns a span. This is a higher order component and as such needs to have a React component as both input and output. If you want to just pass a single JSX element you'd have to type the input differently and not invoke your element prop as its own component:
interface IMyComponentProps {
Component: JSX.Element;
}
const MyComponent: React.FunctionComponent<IMyComponentProps> = ({Component, ...other}) => {
return (<div>{Component}</div>)
};
...
<MyComponent Component={<span>Hey</span>}/>
Maybe a better option:
Use createElement
to build an element dynamically from a string name, I can't think of another way to accomplish that. This also gives you the option to pass a Class/Function component (though the example is only typed for FC's).
interface IMyComponentProps {
Component: React.FunctionComponent | string;
textContent: string;
}
const MyComponent: React.FunctionComponent<IMyComponentProps> = ({Component, children, textContent, ...other}) => {
const newComp = React.createElement(Component, { ...other }, textContent);
return newComp;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With