React18下用@emotion/styled替代makeStyles样式无效求助
问题:React 18 替换 makeStyles 为 @emotion/styled 后样式未达预期
React 18 移除了 makeStyles,我尝试用 @emotion/styled 配置样式,但页面样式和预期不符。
预期样式

实际样式

当前 App.js 代码
import React from 'react'; import { Typography, AppBar } from '@mui/material'; import styled from '@emotion/styled'; import VideoPlayer from './components/VideoPlayer'; import Options from './components/Options'; import Notification from './components/Notification'; // * Style dosyası bağlandı const useStyles = styled(theme => ({ appBar: { borderRadius: 15, margin: '30px 100px', display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', width: '600px', border: '2px solid black', [theme.breakpoints.down('xs')]: { width: '90%', }, }, image: { marginLeft: '15px', }, wrapper: { display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%', }, })); const App = () => { // * Style dosyası çağırıldı //* className olarak elementlere tanımlandı const classes=useStyles(); return ( <div className={classes.wrapper}> <AppBar className={classes.appBar} position='static' color='inherit'> <Typography variant='h2' align='center'> Video Conferencing App </Typography> </AppBar> <VideoPlayer /> <Options> <Notification /> </Options> </div> ) } export default App
错误原因
你混淆了 @emotion/styled 和 makeStyles 的用法:styled 是用来创建带样式的自定义组件,而非生成类名字典。原代码用 styled 模拟 makeStyles 的写法,无法正确生成有效样式类名,导致样式不生效。
解决方案
提供三种可行方案,按需选择:
方案1:使用 MUI 官方 styled 组件模式
直接基于 MUI 组件创建带样式的自定义组件,符合 MUI 推荐的用法:
import React from 'react'; import { Typography, AppBar } from '@mui/material'; import { styled } from '@mui/material/styles'; import VideoPlayer from './components/VideoPlayer'; import Options from './components/Options'; import Notification from './components/Notification'; // 自定义带样式的外层容器 const Wrapper = styled('div')(({ theme }) => ({ display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%', })); // 自定义带样式的AppBar const StyledAppBar = styled(AppBar)(({ theme }) => ({ borderRadius: 15, margin: '30px 100px', display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', width: '600px', border: '2px solid black', // 响应式断点 [theme.breakpoints.down('xs')]: { width: '90%', }, })); const App = () => { return ( <Wrapper> <StyledAppBar position='static' color='inherit'> <Typography variant='h2' align='center'> Video Conferencing App </Typography> </StyledAppBar> <VideoPlayer /> <Options> <Notification /> </Options> </Wrapper> ) } export default App
方案2:用 @emotion/css 生成类名(贴近 makeStyles 用法)
如果习惯类名管理模式,安装 @emotion/css 和 @emotion/react 后,用 css 函数生成类名:
import React from 'react'; import { Typography, AppBar } from '@mui/material'; import { css } from '@emotion/css'; import { useTheme } from '@mui/material/styles'; import VideoPlayer from './components/VideoPlayer'; import Options from './components/Options'; import Notification from './components/Notification'; const App = () => { const theme = useTheme(); const classes = { wrapper: css({ display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%', }), appBar: css({ borderRadius: 15, margin: '30px 100px', display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', width: '600px', border: '2px solid black', [theme.breakpoints.down('xs')]: { width: '90%', }, }) }; return ( <div className={classes.wrapper}> <AppBar className={classes.appBar} position='static' color='inherit'> <Typography variant='h2' align='center'> Video Conferencing App </Typography> </AppBar> <VideoPlayer /> <Options> <Notification /> </Options> </div> ) } export default App
方案3:使用 MUI sx 属性(最简方式)
直接通过组件自带的 sx 属性写样式,支持主题变量和响应式,无需额外依赖:
import React from 'react'; import { Typography, AppBar } from '@mui/material'; import VideoPlayer from './components/VideoPlayer'; import Options from './components/Options'; import Notification from './components/Notification'; const App = () => { return ( <div sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%' }}> <AppBar position='static' color='inherit' sx={{ borderRadius: 15, margin: '30px 100px', display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', width: '600px', border: '2px solid black', // 移动端响应式 ['@media (max-width:600px)']: { width: '90%', } }} > <Typography variant='h2' align='center'> Video Conferencing App </Typography> </AppBar> <VideoPlayer /> <Options> <Notification /> </Options> </div> ) } export default App
内容的提问来源于stack exchange,提问作者idil
相关产品推荐
相关产品推荐

