robertbearclaw.com

Implementing Dark Mode in React with the Provider Pattern

Written on

Chapter 1: Understanding the Provider Pattern

In React development, managing state across multiple components can lead to complex code, especially when prop drilling is involved. To mitigate this, the Provider pattern is commonly utilized alongside React Context. This approach allows you to share data seamlessly across various components without needing to pass props down through every level of your component hierarchy.

Before we get started, ensure that you have Node.js version 18 or higher installed on your system. You can initiate your project with the following command:

npm create vite@latest

Now, let's dive into how to effectively implement dark mode using the Provider pattern in React. First, we’ll look at the advantages of this method.

  • Eliminates the necessity of passing props through multiple component layers.
  • Simplifies code comprehension and maintenance.
  • Useful for managing global application state.

However, it’s important to be cautious. Overusing the Provider pattern can lead to performance issues. If the data within the context changes, all components consuming that context will re-render, even if they don’t utilize the updated information. This can be particularly inefficient for larger applications.

Section 1.1: Setting Up the Dark Mode Provider

The Provider component acts as the context provider for dark mode. It utilizes the useState hook to manage the dark mode state and provides a function to toggle that state.

We can elegantly separate the Provider from other logic. It will maintain the current dark mode state, passing both the isDarkMode value and the toggle function to child components.

import { createContext, PropsWithChildren, useCallback, useState } from "react";

export type DarkModeContextProps = {

isDarkMode: boolean;

toggle(): void;

};

export const DarkModeContext = createContext({

isDarkMode: false,

toggle() {},

});

export function DarkModeProvider({ children }: PropsWithChildren) {

const [isDarkMode, setDarkMode] = useState(false);

const toggle = useCallback(() => setDarkMode((v) => !v), []);

const contextValue = { isDarkMode, toggle };

return (

<DarkModeContext.Provider value={contextValue}>

{children}

</DarkModeContext.Provider>

);

}

By wrapping your application with the DarkModeProvider, you make this context available to all descendant components without intertwining your code with context logic.

import "./App.css";

import { Dashboard } from "./components/Dashboard.tsx";

import { DarkModeProvider } from "./providers/DarkModeProvider.tsx";

function App() {

return (

<DarkModeProvider>

<Dashboard />

</DarkModeProvider>

);

}

export default App;

Section 1.2: Utilizing a Custom Hook for Dark Mode

To streamline access to the dark mode context, we can create a custom hook that uses useContext, enabling components to easily retrieve the current isDarkMode value and the toggle function without the need for explicit prop drilling.

import { useContext } from "react";

import { DarkModeContext } from "../providers/DarkModeProvider.tsx";

export function useDarkMode() {

return useContext(DarkModeContext);

}

Subsection 1.2.1: Creating the Button Component

The button component leverages the useDarkMode hook to access the isDarkMode value, which dynamically adjusts the button’s background color based on the current mode.

import { CSSProperties, PropsWithChildren } from "react";

import { useDarkMode } from "../hooks/useDarkMode.tsx";

type Props = {

onClick?(): void;

};

export function Button({ children, onClick }: PropsWithChildren) {

const { isDarkMode } = useDarkMode();

const style: CSSProperties = {

backgroundColor: isDarkMode ? "#133337" : "#fc6c85",

border: "none",

color: "inherit",

};

return (

<button style={style} onClick={onClick}>

{children}

</button>

);

}

Subsection 1.2.2: Toggle Button Functionality

By clicking the button, users can activate the toggle function, which will switch the dark mode state within the provider.

import { Button } from "./Button.tsx";

import { useDarkMode } from "../hooks/useDarkMode.tsx";

export function ToggleButton() {

const { toggle } = useDarkMode();

return (

<Button onClick={toggle}>Toggle mode</Button>

);

}

Section 1.3: Building the Header Component

This component features a simple menu that incorporates the ToggleButton, allowing users to easily switch between dark and light modes.

import { CSSProperties } from "react";

import { ToggleButton } from "./ToggleButton.tsx";

export function Header() {

const style: CSSProperties = {

display: "flex",

gap: "1rem",

};

return (

<div style={style}>

<span>Products</span>

<span>Categories</span>

<span>Settings</span>

<ToggleButton />

</div>

);

}

Chapter 2: Finalizing the Dashboard Component

The Dashboard component retrieves the isDarkMode value from the context, allowing it to dynamically adjust its styling.

import { CSSProperties } from "react";

import { Header } from "./Header.tsx";

import { useDarkMode } from "../hooks/useDarkMode.tsx";

export function Dashboard() {

const { isDarkMode } = useDarkMode();

const style: CSSProperties = {

color: isDarkMode ? "white" : "black",

backgroundColor: isDarkMode ? "black" : "white",

padding: "8px",

height: "100%",

};

return (

<div style={style}>

<Header />

<h1>Dashboard page</h1>

</div>

);

}

Folder Structure Overview

To keep your project organized, let's review the recommended folder structure.

Project folder structure

Testing Your Implementation

If everything is set up correctly, you should be able to toggle between dark and light themes seamlessly.

Light mode | Dark mode

Thank you for engaging with this article. I hope you found it informative. If you have any feedback or questions, feel free to share them with me!

In Plain English 🚀

Thank you for being a part of the In Plain English community! Before you leave, consider following us on various platforms for more valuable insights.

Discover how to implement a dark/light theme toggle in React using state and context with this tutorial.

Learn the right way to toggle dark mode using the React Context API in this detailed video guide.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

A Nightly Serenade: Understanding the Mockingbird's Song

Explore the nightly serenade of the mockingbird and its impact on the environment and local wildlife.

The Essential Role of Self-Regulation in Emotional Intelligence

Discover how self-regulation enhances emotional intelligence and its significance in personal and professional contexts.

Mastering Vue Applications with the Quasar Framework

Explore how to create visually appealing Vue applications using the Quasar UI library, focusing on tables and sticky headers.

Revamping Your Happiness: Simple Strategies for a Joyful Life

Discover practical strategies to enhance your happiness and foster a more fulfilling life.

Transforming Your Alcohol Recovery: Focus on Growth, Not Just Actions

Discover how to prioritize personal growth over mere actions in your journey to sobriety.

Surrender These 3 Lures to Achieve Success in Life

Discover the three key temptations to abandon for a successful life and learn how they hinder personal growth.

Casting Choices for the New

An analysis of casting decisions for Superman and how they align with comic book representations.

Harnessing the Breath: A Deep Dive into Memory Influence

Discover how breathing patterns can significantly impact memory formation and cognitive functions.