How to implement UI theme switching (dark mode) with React and Recoil
NOTE: This tutorial is relevant to developers using a CSS-in-JS styling approach, e.g. Emotion.js, Material UI, etc.
Step 1: Use Recoil atom for the currently selected theme's name
import { PaletteMode } from "@mui/material";
import { atom } from "recoil";
export const ThemeName = atom<PaletteMode>({
key: "ThemeName",
effects: [/* ... */]
});
Step 2: Use Recoil selector for the currently selected theme object
import { createTheme } from "@mui/material";
import { selector } from "recoil";
export const Theme = selector({
key: "Theme",
dangerouslyAllowMutability: true,
get(ctx) {
const name = ctx.get(ThemeName);
return createTheme(/* ... */);
},
});
useTheme()
, useToggleTheme()
React hooks
Step 3: Add import { useRecoilValue, useRecoilCallback } from "recoil";
export function useTheme() {
return useRecoilValue(Theme);
}
export function useToggleTheme() {
return useRecoilCallback(
(ctx) => () => {
ctx.set(ThemeName, (prev) => (prev === "dark" ? "light" : "dark"));
},
[]
);
}
localStorage
Step 4: Save/restore the currently selected theme name to/from export const ThemeName = atom<PaletteMode>({
key: "ThemeName",
effects: [
(ctx) => {
const storageKey = "theme";
if (ctx.trigger === "get") {
const name: PaletteMode =
localStorage?.getItem(storageKey) === "dark"
? "dark"
: localStorage?.getItem(storageKey) === "light"
? "light"
: matchMedia?.("(prefers-color-scheme: dark)").matches
? "dark"
: "light";
ctx.setSelf(name);
}
ctx.onSet((value) => {
localStorage?.setItem(storageKey, value);
});
},
],
});
ThemeProvider
to the top-level React component
Step 5: Add import { ThemeProvider } from "@mui/material";
import { useTheme } from "../theme/index.js";
function App(): JSX.Element {
const theme = useTheme();
return (
<ThemeProvider theme={theme}>
{/* ... */}
</Theme>
);
}
See app/theme/index.ts
in React Starter Kit
To implement UI theme switching with React and Recoil, you can create a Recoil atom to store the current theme and a theme provider component that uses the stored theme to apply styles.
To enable dark mode, you can add a button or toggle that triggers a function to update the theme atomβs value to βdark.β The theme provider will then apply the appropriate styles based on the selected theme.
As an example, you can use the https://apkbounce.com/grimvalor-mod-apk/ link to demonstrate the UI theme switching in action. When the user selects the dark mode option, the theme provider will apply dark-themed styles to the page, providing a visually appealing experience.
Note that this is a high-level overview of the implementation process, and actual implementation may require more specific details and customization to suit your particular use case.