DEV Community

kleach12
kleach12

Posted on

Dark Mode Guy

Are you team light-mode or dark mode? I am a dark-mode guy, but to each their own. Having a light and dark mode on applications now is almost mandatory, and you might be looked at weird if you are building an app without it. So we will go over how to easily implement themes in our applications using the useContext hook.

First, I should preface why we should use useContext. useContext provides you with the ability to gain access to values anywhere in the application. Your first thought might be, "I can do that by just passing the value down as a prop," and then doing it again, and again, and again until you finally are at the component you need to be. Now that was only 5 levels deep, but imagine if you are working with a massive application that would be time-consuming. The term for that would be "prop drilling," and that is what useContext can prevent and get access to our values in the component we need, no matter how deep they are nested. These values can be any data type or even state variable like in our case, theme.

In the first step of giving our application a theme, we need to create a context. You can do this by creating a new file in your source named ThemeContext.js. In that file, you will need to import createContext where you will set your variable with a value of null and export the variable.

import { createContext } from 'react';

export const ThemeContext = create Context(null);
Enter fullscreen mode Exit fullscreen mode

After you have your variable, you can now go to your App.js file and import both the ThemeContext variable and useState hook. In our case, the whole application needs to be provided with the context, but this does not always have to be the case. If it is only a section, then you would just provide that section with the context. After wrapping all components in ThemeContext.Provider, you will want to create a state variable const { theme, setTheme } = useState('light'). This is where we will hold the state of the theme and where all instances will determine what the styling should be for our components. Now, in order for useContext to work, we need values to be accessible, and how you would do that is using the values prop. We will pass any variable or data that we will need in a component between our Provider. In our case, we will need to pass multiple variables/functions, and you can do that by using double curly brackets curly.

import "./App.css";
import { useState } from "react";
import { ThemeContext} from "./ThemeContext";

function App() {
  const [theme, setTheme] = useState("light");
  return (
    <ThemeContext.Provider value={{theme, setTheme}}>
     //Components Here
    </ThemeContext.Provider>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Now that we have passed our values into our provider, we need to go to the component that is going to switch your theme from light to dark. I personally went with a button on the user’s Dashboard, but in your case, it might be different. But universally, you need it to import both the useContext from react and your ThemeContext variable. You will then create a variable and use a curly bracket to get each individual value from our provider and set that equal to useContext(ThemeContext), and this is how you will be able to access the values. You will then create a button or any input that you would like to have and use the setTheme function to change the button when clicked. In my case, I used icons that change when clicked as well, and I used the theme value to determine which should be showing.

import "./DashNav.css";
import { useContext } from "react";
import { ThemeContext} from "../../AllContext";

export default function ThemeButton() {

const {theme, setTheme} = useContext(ThemeContext);

  const themeButton =
    theme === "light" ? (
      <BsFillMoonFill
        className={"theme_button_" + theme}
        onClick={(e) => handleChangeTheme(e, "dark")}
      />
    ) : (
      <BsBrightnessHigh
        className={"theme_button_" + theme}
        onClick={(e) => handleChangeTheme(e, "light")}
      />
    );

    return (
        {themeButton}
      </div>
    );
Enter fullscreen mode Exit fullscreen mode

Lastly, we need to define the styling for our theme. As you can see from the code above, the classNames include the theme, so when our theme is either dark or light, our CSS will know which class to choose from. In this case, we will need to create separate classes for each ID or class name, with one ending in "dark" and the other in "light", and add the styles of your choice.

.theme_button_dark{
  margin-top: 10%;
  margin-bottom: 10%;
  color: #ffffff;
}

.theme_button_light{
  color: #000000;
  margin-top: 10%;
  margin-bottom: 10%;
}
Enter fullscreen mode Exit fullscreen mode

The final product will look something like this!

Top comments (0)