React: Make theme toggler with just 10 lines of code.

React: Make theme toggler with just 10 lines of code.

Ever wondered how the theme toggler works? Well, here's the explanation and no need to understand and update every DOM for just themes.

ยท

3 min read

Theming is an important feature in many applications, allowing users to customize the color scheme and improve accessibility. In this article, we'll build a theme toggler in React that can switch between a light and dark theme. Here's the live demo and GitHub repo if you ever feel like contributing to advancement or using it in your project as a template.

Context API

We'll use the Context API to manage the theme state and make it available to any component. Context provides a way to pass data through the component tree without having to pass props manually at every level.

First, create a context then create a context provider that wraps our app:

import React, { createContext } from "react";
export const ThemeContext = createContext();

export default function ThemeProvider({ children }) {
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

Any component within this provider can subscribe to the context:

import { ThemeContext } from "./ThemeContext";

export default function App() {
  const { theme, toggleTheme } = React.useContext(ThemeContext);
  return { /* ... */ }; 
}

This allows us to pass these data through the context and use it in any component.

State Management

We'll store the current theme in state and provide setters to toggle the theme.

export default function ThemeProvider({ children }) {
  const [theme, setTheme] = React.useState("light");

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

Now any component can call toggleTheme() from context to switch themes.

Style Switching

We'll dynamically apply a .light or .dark class to the body based on the theme state.

import React from "react";
import { ThemeContext } from "./ThemeContext";

export default function App() {
  const { theme, toggleTheme } = React.useContext(ThemeContext);
  return (
    <div className={`app__container ${theme}`}>
        { /* ... */ }
    </div>
  );
}

Our CSS will have rules for .light and .dark selectors:

*{
    margin: 0;
    padding: 0;

}

.app__container{
    padding: 30px 3vw;
    width: 100vw;
    height: 100vh;
}
.app__container.light{
    background-color: #fff;
}

.app__container.dark{
    background-color: #000;
    color: #fff;
}

Now whenever the theme state changes, the corresponding class will be applied, switching the styles.

Theme Toggle Button

We'll create a button component that toggles the theme:

<button onClick={toggleTheme}>Toggle Theme</button>

When this button is clicked, it will call toggleTheme() from context, toggling the theme state and re-applying the styles.

Storing in Local Storage

We can persist the theme state by storing it in localStorage:

  function toggleTheme() {
    const _theme = theme === "light" ? "dark" : "light";
    localStorage.setItem("13x54r_theme", _theme);
    setTheme(_theme);
  }

Now when the page reloads, it will get the saved theme from localStorage and apply the correct styles. Here's the complete Code for the theme context.

import React, { createContext } from "react";

export const ThemeContext = createContext();

export default function ThemeProvider({ children }) {
  const [theme, setTheme] = React.useState("light");

  React.useEffect(() => {
    const prevTheme = localStorage.getItem("13x54r_theme");
    if (prevTheme) {
      setTheme(prevTheme);
    }
  }, []);

  function toggleTheme() {
    const _theme = theme === "light" ? "dark" : "light";
    localStorage.setItem("13x54r_theme", _theme);
    setTheme(_theme);
  }

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

Hope this helps explain how to build a theme toggler in React! Happy Hacking!

Did you find this article valuable?

Support Lexy Thinks by becoming a sponsor. Any amount is appreciated!

ย