Home > Mobile >  How to pass a functional component as a prop in Typescript and render it?
How to pass a functional component as a prop in Typescript and render it?

Time:02-03

In the code below, how can I:

  1. type the icon properly so React.createElement can create it?
  2. Render the icon if not using React.createElement()?
function DefaultIcon () {
  return <svg></svg>;
}

interface ExampleProps {
  icon?: React.ReactElement; // JSX.IntrinsicElements also errors
}

function Example({ icon = <DefaultIcon /> }: ExampleProps) {
  const Icon = icon;
  return (
    <div>
      {React.createElement(icon)}
      {/* ^Shows Error #1 */}
      {React.createElement(icon as React.ReactElement<any>)}
      {/* ^Shows Error #1 */}
      <Icon />
      {/* ^Shows Error #2 */}
    </div>
  )
}

Error #1

No overload matches this call.
The last overload gave the following error.

Argument of type 'ReactElement<any, string | JSXElementConstructor<any>>' 
is not assignable to parameter of type 'string | FunctionComponent<any> | 
ComponentClass<any, any>'.ts(2769)

Error #2

JSX element type 'Icon' does not have any construct or call signatures.ts(2604)

CodePudding user response:

The issue here is you cannot set jsx as a default value for props in typescript instead try to modify this code

const Icon = icon || DefaultIcon by using this expression we are evaluating that if the code icon is undefined DefaultIcon would be used. then remove the default value in props.

CodePudding user response:

Could you please try this?

function DefaultIcon() {
  return (
    <svg
      width="24"
      height="24"
      viewBox="0 0 24 24"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path
        d="M4.57574 12.5757C4.34142 12.8101 4.34142 13.1899 4.57574 13.4243C4.81005 13.6586 5.18995 13.6586 5.42426 13.4243L4.57574 12.5757ZM15.6 3C15.6 2.66863 15.3314 2.4 15 2.4L9.6 2.4C9.26863 2.4 9 2.66863 9 3C9 3.33137 9.26863 3.6 9.6 3.6H14.4V8.4C14.4 8.73137 14.6686 9 15 9C15.3314 9 15.6 8.73137 15.6 8.4L15.6 3ZM5.42426 13.4243L15.4243 3.42426L14.5757 2.57574L4.57574 12.5757L5.42426 13.4243Z"
        fill="#404040"
      />
    </svg>
  );
}

interface ExampleProps {
  // eslint-disable-next-line react/require-default-props
  icon?: React.ReactNode;
}

function Example({ icon = <DefaultIcon /> }: ExampleProps) {
  return <div>{icon}</div>;
}

export default Example;
  • Related