MUI中将globalTheme扩展至明暗主题时出现非可迭代实例报错
问题描述
我在使用MUI的ThemeProvider时创建了Themes.js文件,文件内定义了统一管理字体排版、圆角等全局样式的globalTheme,需要把globalTheme的配置合并扩展到lightTheme和darkTheme中。这套写法在CodeSandbox环境可以正常运行,但是在VSCode中保存时会抛出如下错误:
TypeError: Invalid attempt to spread non-iterable instance
错误截图:
相关实现代码如下:
import { createTheme } from "@mui/material"; // global theme styles const globalTheme = createTheme({ typography: { fontFamily: "'Inter', sans-serif", body1: { fontSize: "1.25rem", }, }, }); export const lightTheme = createTheme( ...globalTheme, { palette: { mode: "light", // primrary brand color primary: { main: "#b9431d", }, // secondary brand color secondary: { main: "#0074aa", }, text: { // text colors primary: "rgba(32, 26, 24, 1)", secondary: "rgba(32, 26, 24, .8)", disabled: "rgba(32, 26, 24, .38)", }, background: { default: "#F9F2ED", }, }, // overrides for components components: { MuiTooltip: { styleOverrides: { tooltip: { color: "white", backgroundColor: "black", }, arrow: { color: "black", }, }, }, }, }, ); // dark theme styles export const darkTheme = createTheme( ...globalTheme, { palette: { mode: "dark", text: { // text colors primary: "rgba(237, 224, 220, 1)", secondary: "rgba(237, 224, 220, .8)", disabled: "rgba(237, 224, 220, .38)", }, // primary brand color primary: { main: "#ffb59f", }, // secondary brand color secondary: { main: "#7fd2ec", }, background: { default: "#201a18", paper: "#201a18", }, }, // overrides for components components: { MuiTooltip: { styleOverrides: { tooltip: { color: "black", backgroundColor: "white", }, arrow: { color: "white", }, }, }, }, }, );
问题原因
报错核心是对createTheme返回的主题对象使用了错误的展开语法:
- 代码中写的
...globalTheme属于可迭代对象展开语法,仅适用于数组、字符串等实现了迭代器接口的类型,作用是将元素展开到参数列表或数组字面量中 - MUI的
createTheme返回值是普通普通对象,不属于可迭代对象,本地构建环境(VSCode保存时触发的代码校验或转译流程)没有做宽松语法兼容时,就会抛出「尝试展开不可迭代实例」的错误 - CodeSandbox默认的转译配置做了语法兼容处理,所以没有触发报错,但这种写法本身不符合JavaScript语法规范,同时手动展开对象属于浅合并,还会覆盖MUI主题的默认嵌套配置,引发其他样式问题。
另外MUI的createTheme原生支持传入多个配置对象做深度合并,完全不需要手动展开已生成的主题对象。
修复方案
直接把全局主题配置作为参数传入亮色/暗色主题的createTheme即可,MUI会自动完成深度合并,不需要手动展开:
import { createTheme } from "@mui/material"; // 直接定义全局主题配置即可,不需要提前调用createTheme生成实例 const globalThemeOptions = { typography: { fontFamily: "'Inter', sans-serif", body1: { fontSize: "1.25rem", }, }, }; export const lightTheme = createTheme(globalThemeOptions, { palette: { mode: "light", primary: { main: "#b9431d", }, secondary: { main: "#0074aa", }, text: { primary: "rgba(32, 26, 24, 1)", secondary: "rgba(32, 26, 24, .8)", disabled: "rgba(32, 26, 24, .38)", }, background: { default: "#F9F2ED", }, }, components: { MuiTooltip: { styleOverrides: { tooltip: { color: "white", backgroundColor: "black", }, arrow: { color: "black", }, }, }, }, }); export const darkTheme = createTheme(globalThemeOptions, { palette: { mode: "dark", text: { primary: "rgba(237, 224, 220, 1)", secondary: "rgba(237, 224, 220, .8)", disabled: "rgba(237, 224, 220, .38)", }, primary: { main: "#ffb59f", }, secondary: { main: "#7fd2ec", }, background: { default: "#201a18", paper: "#201a18", }, }, components: { MuiTooltip: { styleOverrides: { tooltip: { color: "black", backgroundColor: "white", }, arrow: { color: "white", }, }, }, }, });
如果确实需要基于已经生成的globalTheme实例扩展,直接把实例作为参数传入createTheme即可,不要使用迭代展开语法:
const globalTheme = createTheme({ typography: { fontFamily: "'Inter', sans-serif", body1: { fontSize: "1.25rem", }, }, }); export const lightTheme = createTheme(globalTheme, { // 亮色主题独有配置 });
内容的提问来源于stack exchange,提问作者Josh Cusick
相关产品推荐
相关产品推荐

