设置深色主题不会覆盖以前的主题

Setting dark theme doesn't override previous theme

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

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

当前行为

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

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

重现步骤

Live example in CodeSandbox

步骤:

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

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

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

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