升级Material UI 5后,如何避免Styled组件新增div破坏原有样式?
问题描述
原本使用React Fragment包裹多组件的React代码,执行npx @mui/codemod v5.0.0/jss-to-styled src升级到Material UI V5后,codemod工具自动用div替换了Fragment作为Styled组件的根节点,导致原有样式失效。需要避免引入额外div的同时保留原有样式。
旧代码
<> {key === '1' && <Box className={classes.item1}>content</Box>} {key === '2' && <Box className={classes.item2}>content</Box>} </>
升级后的代码
// TODO jss-to-styled codemod: The Fragment root was replaced by div. Change the tag if needed. const Root = styled('div')(({ theme }) => { return { [`& .${classes.item1}`]: { display: 'flex', alignItems: 'center', justifyContent: 'flex-end', paddingRight: theme.spacing(1) } } }) <Root> {key === '1' && <Box className={classes.item1}>content</Box>} {key === '2' && <Box className={classes.item2}>content</Box>} </Root>
解决方案
直接为内部组件设置样式,回归Fragment包裹
把原父容器的样式直接迁移到内部Box组件上,不再依赖父容器的后代选择器,这样就能继续用Fragment避免多余DOM节点:// 将item1的样式封装为独立Styled组件 const StyledItem1 = styled(Box)(({ theme }) => ({ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', paddingRight: theme.spacing(1) })) // 继续使用Fragment包裹,无额外DOM节点 <> {key === '1' && <StyledItem1>content</StyledItem1>} {key === '2' && <Box className={classes.item2}>content</Box>} </>将Styled根组件改为React.Fragment
Material UI的styled支持将React.Fragment作为样式化目标,不会渲染额外DOM节点。但Fragment无法作为CSS选择器的父节点,因此需要调整原有样式写法:// 创建无DOM节点的Styled Fragment容器 const Root = styled(React.Fragment)(() => ({})) <Root> {key === '1' && <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', paddingRight: theme => theme.spacing(1) }}>content</Box>} {key === '2' && <Box className={classes.item2}>content</Box>} </Root>用Box组件并指定component为Fragment
如果想保留原有样式结构,可使用Material UI的Box作为Styled根组件,同时指定component={React.Fragment}让它不渲染DOM节点(注意:若样式依赖父DOM节点,此方法会失效,需改用内部组件样式):const Root = styled(Box)(({ theme }) => ({ [`& .${classes.item1}`]: { display: 'flex', alignItems: 'center', justifyContent: 'flex-end', paddingRight: theme.spacing(1) } })) <Root component={React.Fragment}> {key === '1' && <Box className={classes.item1}>content</Box>} {key === '2' && <Box className={classes.item2}>content</Box>} </Root>
内容的提问来源于stack exchange,提问作者keerti
相关产品推荐
相关产品推荐

