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

React JSX自定义元素className未转换为class属性如何解决

问题现象

在React项目中为Web Components自定义元素编写TS类型声明后,JSX中传入的className属性没有像内置HTML元素一样被转换为标准的class属性,而是被直接渲染为全小写的classname属性。

涉及的TS类型定义如下:

declare global {
    // eslint-disable-next-line @typescript-eslint/no-namespace
    namespace JSX {
        interface IntrinsicElements {
            'd3fc-group': DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
            'd3fc-svg': DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
        }
    }
}

组件中编写的JSX结构:

return (
    <div ref={d3Container} className='main_layout' data-testid={'chart'}>
        <d3fc-group
            id='group'
            className='hellooo'
            style={{ display: 'flex', height: '100%', width: '100%', flexDirection: 'column' }}
            auto-resize>
        </d3fc-group>
    </div>
);

实际渲染出的异常DOM结构:

<d3fc-group id="group" classname="hellooo" auto-resize="true" style="display: flex; height: 100%; width: 100%; flex-direction: column;"><div style="flex: 1 1 0%; display: flex; flex-direction: column;"></d3fc-group>
根本原因

TS的类型声明仅做静态类型校验,不会改变React运行时的属性处理逻辑。
React 18及更早版本对内置HTML元素和自定义元素(标签名包含连字符的元素)采用两套属性处理逻辑:

  • 内置元素会自动完成属性名映射,比如将className转为class、htmlFor转为for、对事件名和布尔属性做标准化处理
  • 自定义元素默认直接将JSX传入的属性名转为小写后透传到DOM节点,不会做上述属性映射,因此className会被直接渲染为classname
解决方案

根据使用的React版本选择对应方案即可:

React 18及更低版本

  • 方案1:直接在自定义元素上使用标准HTML属性名,用class代替className,React会正常透传该属性到DOM。同步调整TS类型避免校验报错:
// JSX中直接写class属性
<d3fc-group
    id='group'
    class='hellooo'
    style={{ display: 'flex', height: '100%', width: '100%', flexDirection: 'column' }}
    auto-resize>
</d3fc-group>
// 调整TS类型定义,增加class属性支持
declare global {
    // eslint-disable-next-line @typescript-eslint/no-namespace
    namespace JSX {
        interface IntrinsicElements {
            'd3fc-group': DetailedHTMLProps<HTMLAttributes<HTMLDivElement> & { class?: string }, HTMLDivElement>;
            'd3fc-svg': DetailedHTMLProps<HTMLAttributes<HTMLDivElement> & { class?: string }, HTMLDivElement>;
        }
    }
}
  • 方案2:如果需要统一保持className的写法习惯,可以使用工具将自定义元素包装为标准React组件,包装后的组件会自动完成属性名映射,和内置元素行为保持一致。

React 19及更高版本

React 19重构了自定义元素的处理逻辑,默认就会和内置HTML元素一样自动完成className转class、样式对象序列化、事件名标准化等操作,直接升级React版本即可,不需要修改现有业务代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 16:36:43