如何在Next.js应用中使用@mui/material的styled让emotion组件选择器生效
报错根因
报错Error: Component selectors can only be used in conjunction with @emotion/babel-plugin的核心原因是:从@mui/material导出的styled工具,默认未被@emotion/babel-plugin识别,而组件选择器语法必须依赖该babel插件做编译时处理才能生效;你直接引入@emotion/styled运行正常是因为项目已对该包的导出做了插件适配。
可用解决方案
方案1:配置插件适配MUI的styled(推荐)
这是最彻底的解决方式,配置后可以正常使用MUI导出的所有styled能力:
- 安装依赖
npm install @emotion/babel-plugin --save-dev # 或使用yarn yarn add @emotion/babel-plugin -D
- 修改项目babel配置(
.babelrc/babel.config.json/babel.config.js),添加如下配置:
{ "plugins": [ [ "@emotion", { "importMap": { "@mui/material/styles": { "styled": { "canonicalImport": ["@emotion/styled", "default"] } } } } ] ] }
- 如果你使用Next.js且开启了SWC编译器,不需要额外安装babel插件,直接修改
next.config.js即可:
/** @type {import('next').NextConfig} */ const nextConfig = { compiler: { emotion: { importMap: { "@mui/material/styles": { styled: { canonicalImport: ["@emotion/styled", "default"], }, }, }, }, }, } module.exports = nextConfig
方案2:使用类选择器替代组件选择器
如果不想修改编译配置,可以给需要被选择的目标组件添加自定义类名,用类选择器替代组件选择器语法:
import { styled, Button } from '@mui/material' // 给目标组件加固定类名 const TargetButton = styled(Button)({ // 目标组件自身样式 }) TargetButton.defaultProps = { className: 'target-button' } // 用类选择器实现原有选择逻辑 const Wrapper = styled('div')({ '.target-button': { marginLeft: '8px' } })
方案3:保持从@emotion/styled引入styled
如果当前使用@emotion/styled无其他兼容问题,可直接沿用该引入方式,MUI组件完全兼容emotion的styled语法,不需要额外调整。
内容的提问来源于stack exchange,提问作者Andrei Sirotin
相关产品推荐
相关产品推荐

