React中Emotion属性转style对象触发两类报错的问题咨询
MUI Emotion styled 自定义属性相关问题修复
问题复现
按照自定义属性传参实现条件样式的思路编写代码后,出现两个异常:
- 页面加载触发React警告:自定义的
noheader布尔属性被透传到原生div节点,提示非布尔属性接收了true值 - TypeScript编译报错:提示组件调用时缺少必填的
theme属性,和MUI自动注入theme的默认行为不符
原问题代码:
import {Paper, useTheme, Theme} from "@mui/material"; export const StyledInsidePaperDiv = styled('div')(({theme, noheader}: {theme: Theme, noheader: boolean}) => css` padding: ${theme.spacing(2)}; padding-top: ${theme.spacing(noheader ? 2 : 0.25)}; ${theme.breakpoints.down('sm')} { padding-left: ${theme.spacing(1)}; padding-right: ${theme.spacing(1)}; } `); export function MyPaper() { const theme = useTheme(); return <Paper> <StyledInsidePaper theme={theme} noheader={true}> inside </StyledInsidePaper> </Paper> }
问题成因
- DOM透传警告:Emotion的styled组件默认会将所有传入props透传给底层原生DOM元素,
noheader是仅用于样式计算的自定义属性,不属于div原生支持的HTML属性,布尔值直接透传就会触发React的非标准属性警告。 - TS类型报错:定义样式入参时手动声明了
theme字段,覆盖了MUI/Emotion自动注入theme的默认类型推导,导致TS判定theme是需要手动传入的必填属性。
修复方案
核心修复逻辑
- 自定义样式属性使用Emotion官方的*临时属性(Transient Props)*规则:属性名加
$前缀,这类属性仅在样式计算阶段生效,不会透传到真实DOM节点,直接消除属性透传警告。 - 自定义props类型通过styled的泛型参数传入,不要在类型中手动声明
theme,框架会自动合并theme的类型推导,无需手动传值。
修复后代码
import { styled, Paper, Theme } from "@mui/material"; // 如果保留css模板语法写法,需要额外导入css:import { css } from "@emotion/react"; // 仅定义自定义业务属性,不要包含theme interface StyledInsidePaperDivProps { $noheader: boolean; } // 通过泛型传入自定义props类型 export const StyledInsidePaperDiv = styled('div')<StyledInsidePaperDivProps>(({ theme, $noheader }) => ({ padding: theme.spacing(2), paddingTop: theme.spacing($noheader ? 2 : 0.25), [theme.breakpoints.down('sm')]: { paddingLeft: theme.spacing(1), paddingRight: theme.spacing(1), } })); // 如果偏好css模板语法,可替换为以下写法 // export const StyledInsidePaperDiv = styled('div')<StyledInsidePaperDivProps>(({ theme, $noheader }) => css` // padding: ${theme.spacing(2)}; // padding-top: ${theme.spacing($noheader ? 2 : 0.25)}; // ${theme.breakpoints.down('sm')} { // padding-left: ${theme.spacing(1)}; // padding-right: ${theme.spacing(1)}; // } // `); export function MyPaper() { // 无需手动调用useTheme传入theme,MUI会自动完成注入 return ( <Paper> <StyledInsidePaperDiv $noheader={true}> inside </StyledInsidePaperDiv> </Paper> ) }
内容的提问来源于stack exchange,提问作者paul23
相关产品推荐
相关产品推荐

