3

I have a Sidebar component which passes unique icons into a SidebarRow child component via props.

import SidebarRow from './SidebarRow';
import {
    CogIcon,
    UsersIcon
} from '@heroicons/react/solid';

const Sidebar: React.FC = () => {
    return (
        <div className="p-2 mt-5 max-w-5xl xl:min-w-lg">
            <SidebarRow src="" title="Tom Mc" />
            <SidebarRow Icon={UsersIcon} title="Friends" />
            <SidebarRow Icon={CogIcon} title="Account" />
        </div>    
    )
}

export default Sidebar;

Within the SidebarRow component an interface defines the incoming props. Here I am attempting to conditionally render either an image or an Icon, depending on which is passed in.

import React from "react";

interface SidebarRowProps {
    src?: string
    Icon?: React.FC
    title: string
};

const SidebarRow: React.FC<SidebarRowProps> = ({ src, Icon, title }) => {
    return (
        <div className="">
            {src && (
                <img className="rounded-full" src={src} alt="" width="30" height="30" />            
            )}
            {Icon && (
                <Icon className="h-8 w-8 text-blue-500" />
            )}
            <p className="hidden sm:inline-flex font-medium">{title}</p>
        </div>    
    )
};

export default SidebarRow;

I am receiving the below error for the className attribute on the Icon component:

Type '{ className: string; }' is not assignable to type 'IntrinsicAttributes & { children?: ReactNode; }'.
  Property 'className' does not exist on type 'IntrinsicAttributes & { children?: ReactNode; }'.ts(2322)
(JSX attribute) className: string

How can I define the Icon type so that the className property does not throw this error?

Thank you!

5
  • try this: Icon?: React.SVGProps<SVGSVGElement>, if found in the source code of your icon library this type, className does not exists on type React.FC Commented Jul 16, 2021 at 10:14
  • The Sidebar component then flags an error for the elements passed to Icon via props: Value of type '(props: SVGProps<SVGSVGElement>) => Element' has no properties in common with type 'SVGProps<SVGSVGElement>'. Did you mean to call it?ts(2560) Sidebar.tsx(11, 30): Did you mean to call this expression? (alias) function UsersIcon(props: React.ComponentProps<'svg'>): JSX.Element import UsersIcon Commented Jul 16, 2021 at 10:18
  • Can you share your full code so I can try it ? Commented Jul 16, 2021 at 10:19
  • Thanks, here's a sandbox: codesandbox.io/s/hardcore-water-r4scl Commented Jul 16, 2021 at 10:27
  • 3
    Use React.ComponentType instead of React.FC. Example: Icon?: React.ComponentType<React.HtmlHTMLAttributes<HTMLElement>>. You can change React.HtmlHTMLAttributes<HTMLElement> to the Props Type of your Icon. Commented Jul 16, 2021 at 10:28

2 Answers 2

10

The following code works fine

import React from "react";

interface SidebarRowProps {
    src?: string
    Icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>
    title: string
};

Sign up to request clarification or add additional context in comments.

Comments

6

Heroicon types were changed in 2.0.17. Per regarding the icons type signature #981, the correct way to type icons is now one of

type Icon = React.FC<Parameters<typeof UsersIcon>[0]>

or

type IconSVGProps = React.PropsWithoutRef<React.SVGProps<SVGSVGElement>> & React.RefAttributes<SVGSVGElement>
type IconProps = IconSVGProps & {
      title?: string
      titleId?: string
 }

 type Icon = React.FC<IconProps>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.