首页 > 解决方案 > 设置深色主题不会覆盖以前的主题

问题描述

如果我更改主题的 1 种颜色,主题将保持原样。

但是如果我尝试更新调色板类型,它就不起作用。它只是创建一个新主题。但在那种情况下,我放弃了我之前的所有修改。

当前行为

如果覆盖颜色,调色板类型将保持不变。如果我覆盖调色板类型。它不起作用。如果使用新的调色板类型创建新主题,它可以工作,但会丢失以前的更改。

预期行为 更改调色板类型后,我仍应看到我的原色。

重现步骤

CodeSandbox 中的实时示例

脚步:

  1. 单击更改主题按钮。您将看到主题如何切换。并且原色是蓝色
  2. 单击更改为随机颜色。您将看到原色如何变化。而且主题是一样的。
  3. 单击更改主题按钮。您将看到主题如何切换。而原色又是蓝色

标签: reactjsmaterial-uithemes

解决方案


您遇到问题是因为您尝试使用空对象或从 material-ui 完全生成的主题对象。

解决问题的一个简单方法是通过上下文传递当前主题并基于它创建一个新主题。这将让 material-ui 根据类型暗/亮生成主题的所有其他值。

function ThemeCustomProvider({ children }) {
  const [theme, setTheme] = React.useState(defaultTheme());

  return (
    <ThemeProvider theme={createMuiTheme(theme)}>
      <ThemeSetContext.Provider value={{ theme, setTheme }}>
        <CssBaseline />
        {children}
      </ThemeSetContext.Provider>
    </ThemeProvider>
  );
}

在您的组件中,我们将使用lodash/merge旧主题与新值合并

const { theme, setTheme } = useThemeSetContext(); // The function taht will update the theme

  const handleChangeDark = () => {
    const newTheme = merge(
      {}, // Use a new object. We don't mutate data in React
      theme, // Copy the old theme values
      {
        palette: {
          type: theme.palette.type === "light" ? "dark" : "light"
        }
      }
    );
    setTheme(newTheme); // Update the theme with the new theme that only has change dark type
    setMessage(
      "The theme change between dark and light, but overrides the primary color, so the primary color are always blue."
    );
  };

  const handleChangeColor = () => {
    const newTheme = merge(
      {},
      theme,
      {
        palette: {
          primary: {
            main: getRandomColor() // The new value
          }
        }
      }
    );
    setTheme(newTheme); // Update the theme with the new object that keeps the previous values like palette type
    setMessage(
      "The theme change the primary color, keeping the theme dark/light theme."
    );
  };

这是您的代码框更新了这些更改:

https://codesandbox.io/s/so-material-ui-changetheme-type-qdbe9


推荐阅读