Pab Iy
Pab Iy

Reputation: 61

Setting dark theme doesn't override previous theme

If I change 1 color of the theme, the theme keeps as it was.

But If I try to update the palette type, it doesn't work. It just work creating a new theme. But in that case I loose all my previous modifications.

Current Behavior

If override a color, the palette type stays like it was. If I override the palette type. It doesn't work. If a create a new theme with the new palette type, it works, but loosing the previous changes.

Expected Behavior Changing the palette type, I should still see my primary colors.

Steps to Reproduce

Live example in CodeSandbox

Steps:

  1. Click in the Change theme button. You will see how the theme toggle. And the primary color is blue
  2. Click on Change to random color. you will see how the primary color changes. And the theme is the same.
  3. Click in the Change theme button. You will see how the theme toggle. And the primary color is blue again

Upvotes: 2

Views: 430

Answers (1)

abumalick
abumalick

Reputation: 2346

You had problems because you were trying with an empty object or with the fully generated theme object from material-ui.

A simple solution to your problem is to pass your current theme through the context and create a new theme based on it. This will let material-ui generate all the other values of the theme based on type 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>
  );
}

In your component we will use lodash/merge to merge the old theme with the new values

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."
    );
  };

Here is your codesandbox updated with these changes:

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

Upvotes: 1

Related Questions