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:

Arc Browser’s Exciting New Feature: Previews Explained

Discover the latest Previews feature of the Arc browser, enhancing productivity with quick glances at your favorite services.

Embracing Conscious Choices: The Journey from Coulda to Woulda

This narrative explores the transformative journey of conscious choices, emphasizing empathy and self-awareness through the lens of high sensitivity.

The Olympic Art of Procrastination: A Comedic Journey

Explore the humorous world of procrastination, where avoiding tasks becomes an art form worthy of Olympic status.

Rediscovering Nature Through Running: A Personal Journey

A personal reflection on how changing my running habits deepened my connection with nature.

Embracing Mistakes for Personal Growth and Resilience

Discover how embracing mistakes can lead to personal growth and stronger relationships through accountability and learning.

Empower Yourself: 3 Steps to Overcome Feelings of Powerlessness

Discover three effective strategies to regain control and empower yourself when you feel powerless.

Transforming Limiting Beliefs: Steps to Overcome Negative Self-Talk

Discover how to break free from limiting beliefs and negative self-talk to unlock your true potential and achieve your dreams.

Unexpected Love in Business Development: A Personal Journey

Discovering unexpected inspiration from a business consultant.