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

PancakeSwap前端代码构建阶段出现'Icon'无法作为JSX组件的类型错误求助

解决TypeScript错误:'Icon' cannot be used as a JSX component

这个错误本质是TypeScript无法确认你传入的icon属性是一个有效的JSX组件类型。从你的代码来看,icon的类型被定义为Element | Component<any, any, any>,而JSX要求组件必须是组件类/函数或者DOM元素标签字符串,直接使用Component类型会因为render()返回值的类型兼容问题报错。

下面是具体的修复步骤:

1. 修正icon的类型定义(最优方案)

首先找到SubMenuItemsProps的类型定义文件(./types),把icon的类型从Element | Component<any, any, any>改成React.ElementType——这个类型是React内置的,专门用来表示可以作为JSX组件的类型(包含函数组件、类组件、DOM标签):

// 在 ./types 文件中
import React from 'react';

export interface SubMenuItemsProps {
  // 其他属性...
  icon?: React.ElementType;
}

修改后,TypeScript就能正确推断Icon是合法的JSX组件,不需要额外处理。

2. 如果无法修改props类型,添加类型断言/守卫

如果你没办法修改SubMenuItemsProps的定义(比如是第三方库的类型),可以在使用icon的时候手动做类型断言,告诉TypeScript这是一个有效的组件类型:

// 替换你代码中的 const Icon = icon;
const Icon = icon as React.ElementType;

或者更严谨一点,添加类型守卫区分“已渲染的元素”和“组件”:

{icon && (
  typeof icon === 'object' 
    ? icon // 如果是已经渲染好的React元素,直接显示
    : <Icon color={href === activeItem ? "secondary" : "textSubtle"} mr="4px" /> // 如果是组件,再渲染
)}

3. 额外检查:确保传入的icon值正确

还要确认你传入SubMenuItems的icon属性是组件本身(比如OpenNewIcon),而不是已经渲染的元素(比如<OpenNewIcon />)——如果是后者,直接渲染即可,不需要用<Icon />的方式调用。

修改后的完整代码示例:

import React from "react";
import { Box } from "../Box";
import { DropdownMenuItemType } from "../DropdownMenu/types";
import MenuItem from "../MenuItem/MenuItem";
import { OpenNewIcon } from "../Svg";
import StyledSubMenuItems from "./styles";
import { SubMenuItemsProps } from "./types";

const SubMenuItems: React.FC<SubMenuItemsProps> = ({ items = [], activeItem, isMobileOnly = false, ...props }) => {
  return (
    <StyledSubMenuItems justifyContent={[isMobileOnly ? "flex-end" : "start", null, "center"]} {...props} pl={["12px", null, "0px"]} $isMobileOnly={isMobileOnly} >
      {items.map(({ label, href, icon, itemProps, type }) => {
        const isExternalLink = type === DropdownMenuItemType.EXTERNAL_LINK;
        const linkProps = isExternalLink ? { as: "a", target: "_blank", } : {};
        return (
          label && (
            <Box key={label} mr="20px">
              <MenuItem href={href} isActive={href === activeItem} variant="subMenu" {...itemProps} {...linkProps}>
                {/* 区分组件和已渲染元素 */}
                {icon && (
                  typeof icon === 'function' || typeof icon === 'string'
                    ? React.createElement(icon, { color: href === activeItem ? "secondary" : "textSubtle", mr: "4px" })
                    : icon
                )}
                {label}
                {isExternalLink && (
                  <Box display={["none", null, "flex"]} style={{ alignItems: "center" }} ml="4px">
                    <OpenNewIcon color="textSubtle" />
                  </Box>
                )}
              </MenuItem>
            </Box>
          )
        );
      })}
    </StyledSubMenuItems>
  );
};

export default SubMenuItems;

这样就能解决构建时的TypeScript类型错误了。

内容的提问来源于stack exchange,提问作者Krishan Bandara Karunathilaka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 19:27:41