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

Next.js+TypeScript中如何以JSX形式传递组件作为Props?

解决Next.js+TypeScript中传递预渲染JSX组件的服务端错误

问题场景

在Next.js结合TypeScript的项目中,循环渲染数组项时,将<InboxIcon strokeWidth={6}/>这类预渲染的JSX元素存入数组并作为props传递,会触发服务端错误:「元素类型无效:期望字符串或类/函数但得到对象」;但直接传入InboxIcon组件本身则可正常运行,需要让第一种传递方式生效。

相关代码

index.tsx

import { Card } from '@/components/Card'
import { InboxIcon } from '@/components/InboxIcon'

const features = [
    {        
        title: 'hello',
        icon: <InboxIcon strokeWidth={6}/>        
    },
]

export default function Home() {
    return (
        <>
            {features.map((feature) => (
                <Card
                    key={feature.title}
                    icon={feature.icon}                                        
                />
            ))}
        </>
    )
}

Card.tsx

interface Props {
    title: string    
    icon: any
}

export function Card(props: Props) {
    return (
        <div>                            
            <props.icon className="display-icon"/>                                                                                                                     
            {props.title}
        </div>
    )
}

InboxIcon.tsx

interface Props {
    className?: string
    strokeWidth: number
}

export function InboxIcon(props: Props) {
    return (
        <svg
            className={props.className}
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 512 512"
            aria-hidden="true"
        >            
            <path                
                strokeWidth={props.strokeWidth}                
                fill="currentColor"                
                d="M 70 110 C 70 140, 110 140, 110 110"
            />
        </svg>
    )
}

错误原因

你在数组中存入的<InboxIcon strokeWidth={6}/>是已经通过React.createElement创建好的JSX元素对象,但在Card组件中却用<props.icon />的方式把它当作组件类/函数来调用——React渲染时会校验组件类型,期望传入的是可执行的组件,而非已渲染完成的元素对象,因此服务端抛出类型错误。

解决方案

方案一:直接渲染传入的JSX元素

修改Card.tsx,将组件调用语法改为直接渲染JSX元素的语法,同时如果需要给图标添加className,直接在数组中预渲染时传入:

修改后的index.tsx

const features = [
    {        
        title: 'hello',
        icon: <InboxIcon strokeWidth={6} className="display-icon"/>        
    },
]

修改后的Card.tsx

interface Props {
    title: string    
    icon: React.ReactNode
}

export function Card(props: Props) {
    return (
        <div>                            
            {props.icon}                                                                                                                     
            {props.title}
        </div>
    )
}

方案二:存储组件与props,动态渲染

如果需要在Card组件中动态给图标传递额外属性(比如统一添加className),可以在数组中存储组件本身和对应的props,而非预渲染的JSX元素:

修改后的index.tsx

const features = [
    {        
        title: 'hello',
        icon: InboxIcon,
        iconProps: { strokeWidth: 6 }        
    },
]

修改后的Card.tsx

import type { ElementType } from 'react';

interface Props {
    title: string    
    icon: ElementType
    iconProps?: Record<string, unknown>
}

export function Card(props: Props) {
    const Icon = props.icon;
    return (
        <div>                            
            <Icon {...props.iconProps} className="display-icon"/>                                                                                                                     
            {props.title}
        </div>
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 11:53:08