You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+TypeScript中Icon作为Props传递的样式与类型冲突解决

解决Icon类型与样式设置的冲突问题

方案一:传递组件而非组件实例(推荐)

这种方式符合React组件复用的最佳实践,能完美适配TypeScript类型校验。

修改父组件(Sidebar.tsx)

将原有的<HomeIcon />组件实例改为直接传递HomeIcon组件本身:

import SidevarNavigationItem from "./SidevarNavigationItem"
import { HomeIcon } from "@heroicons/react/24/solid"
import { StarIcon } from "@heroicons/react/24/solid"

const Sidebar = () => {
  return (
    <nav
      id="sidebar"
      className="p-2 mt-5 max-w-2xl xl:min-w-fit sticky top-20 flex-grow-0.2 text-center h-screen"
    >
      <div id="navigation">
        <SidevarNavigationItem Icon={HomeIcon} name="Homepage" source="/" />
        <SidevarNavigationItem
          Icon={StarIcon}
          name="Tournaments"
          source="/tournaments"
        />
      </div>
    </nav>
  )
}

export default Sidebar

子组件(SidebarNavigationItem.tsx)修正细节

保持React.ElementType类型,同时修正拼写错误(classname改为className):

import Link from "next/link"
import { FunctionComponent } from "react"

interface Props {
  Icon: React.ElementType
  name: string
  source: string
}

const SidevarNavigationItem: FunctionComponent<Props> = ({
  Icon,
  name,
  source,
}) => {
  return (
    <Link href={source}>
      <div className="flex items-center cursor-pointer text-3xl space-x-5 justify-center">
        {Icon && <Icon className="h-8 w-8 text-red-500" />}
        <p className="hidden sm:inline-flex font-medium">{name}</p>
      </div>
    </Link>
  )
}

export default SidevarNavigationItem

方案二:传递组件实例并通过克隆添加样式

如果坚持在父组件传递<HomeIcon />这类实例,可以用React.cloneElement克隆元素并追加样式:

修改子组件(SidebarNavigationItem.tsx)

import Link from "next/link"
import { FunctionComponent, cloneElement } from "react"

interface Props {
  Icon: JSX.Element
  name: string
  source: string
}

const SidevarNavigationItem: FunctionComponent<Props> = ({
  Icon,
  name,
  source,
}) => {
  return (
    <Link href={source}>
      <div className="flex items-center cursor-pointer text-3xl space-x-5 justify-center">
        {Icon && cloneElement(Icon, {
          className: `${Icon.props.className || ""} h-8 w-8 text-red-500`
        })}
        <p className="hidden sm:inline-flex font-medium">{name}</p>
      </div>
    </Link>
  )
}

export default SidevarNavigationItem

父组件保持不变

继续传递<HomeIcon />即可,子组件会自动合并原有样式与新增样式。

错误原因说明

  • React.ElementType代表的是组件类型(如函数组件、类组件),而你父组件传递的<HomeIcon />是已渲染完成的JSX元素实例,类型为JSX.Element,两者类型不兼容,因此TypeScript抛出错误。
  • 当把类型设为JSX.Element时,直接修改元素props(如添加className)会报错,因为JSX元素是不可变的,必须通过克隆的方式修改。

内容的提问来源于stack exchange,提问作者lool

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 19:51:52