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

如何通过组件名称正确创建并渲染React组件?解决TS报错

解决动态渲染React组件的TypeScript错误及规范实现

当前错误的修复

1. 修正返回类型错误

你的getFormatter函数返回类型写的是React.Component,这是组件的实例类型,但JSX需要的是组件的构造函数/函数类型(即React.ComponentType)。将返回类型修改为React.ComponentType<any>(若需要更严谨的类型约束,可自定义props类型):

function getFormatter(type: string, name: string, meta: JsonApiMetaAttributeType): React.ComponentType<any> {
    let formatterName = capitalizeFirstLetter(meta[type][name].type) + 'Formatter'
    if (!isFormatterKey(formatterName)) {
        formatterName = 'StringFormatter'
    }
    return Formatter[formatterName]
}

2. 修正JSX标签笔误

代码中</FormatterComponent2>是笔误,需改为</FormatterComponent>:

{
    Object.keys(item.attributes).map((attrName: string) => {
        const FormatterComponent = getFormatter(item.type, attrName, meta)
        return (
            <td key={"data-cell-" + attrName}>
                <FormatterComponent>
                    {item.attributes[attrName]}
                </FormatterComponent>                      
            </td>
        )
    })
}

规范的动态组件渲染模式

1. 明确组件映射与类型约束

单独定义组件映射对象,配合TypeScript类型系统约束可用组件,让类型检查更严格:

// 定义Formatter组件的通用props类型
type FormatterProps = {
    children: React.ReactNode;
    // 可添加其他通用props字段
};

// 定义组件映射类型
type FormatterMap = Record<string, React.ComponentType<FormatterProps>>;

// 按需导入组件并创建映射(比import *更清晰可控)
import StringFormatter from './StringFormatter';
import NumberFormatter from './NumberFormatter';
// 导入其他Formatter组件...

const formatterMap: FormatterMap = {
    StringFormatter,
    NumberFormatter,
    // 注册其他组件...
};

// 简化类型守卫函数
function isFormatterKey(key: string): key is keyof typeof formatterMap {
    return key in formatterMap;
}

2. 优化动态组件获取逻辑

function getFormatter(type: string, name: string, meta: JsonApiMetaAttributeType): React.ComponentType<FormatterProps> {
    const formatterName = `${capitalizeFirstLetter(meta[type][name].type)}Formatter`;
    // 直接返回目标组件或默认组件,避免额外变量赋值
    return formatterMap[formatterName as keyof typeof formatterMap] || formatterMap.StringFormatter;
}

3. 简化渲染逻辑

使用Object.entries替代Object.keys,直接获取属性名与值,代码更简洁:

{
    Object.entries(item.attributes).map(([attrName, attrValue]) => {
        const FormatterComponent = getFormatter(item.type, attrName, meta);
        return (
            <td key={`data-cell-${attrName}`}>
                <FormatterComponent>
                    {attrValue}
                </FormatterComponent>
            </td>
        );
    })
}

4. 额外优化建议

  • 若不同组件有差异化props,可通过React.ComponentType泛型或联合类型适配
  • 将默认组件设为可配置项,避免硬编码StringFormatter
  • 对meta[type][name].type添加空值检查,防止访问不存在的属性引发报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 22:29:55