Implementing dark mode persistence using local storage in a Next.js application involves using both React state and the browser's local storage to store and retrieve the user's preferred theme. Here's a step-by-step guide to achieve this:
Create a Theme Context: First, you need to create a React context to manage the theme state. This context will be used to share the theme state across different components.
jsx// themes.js
import { createContext, useContext, useState } from 'react';
const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => useContext(ThemeContext);
Wrap Your App with the Theme Provider:
Wrap your entire Next.js app with the ThemeProvider
to make the theme context available to all components.
jsx// pages/_app.js
import { ThemeProvider } from '../path-to/themes';
function MyApp({ Component, pageProps }) {
return (
<ThemeProvider>
<Component {...pageProps} />
</ThemeProvider>
);
}
export default MyApp;
Implement Dark Mode Toggle Button:
Create a component that allows users to toggle between light and dark modes. This component will use the toggleTheme
function from the theme context.
jsx// components/ThemeToggle.js
import { useTheme } from '../path-to/themes';
const ThemeToggle = () => {
const { theme, toggleTheme } = useTheme();
return (
<button onClick={toggleTheme}>
Switch to {theme === 'light' ? 'dark' : 'light'} mode
</button>
);
};
export default ThemeToggle;
Use Local Storage for Theme Persistence:
Update the ThemeProvider
to use local storage for theme persistence.
jsx// themes.js
import { createContext, useContext, useState, useEffect } from 'react';
const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const storedTheme = localStorage.getItem('theme') || 'light';
const [theme, setTheme] = useState(storedTheme);
const toggleTheme = () => {
const newTheme = theme === 'light' ? 'dark' : 'light';
setTheme(newTheme);
localStorage.setItem('theme', newTheme);
};
useEffect(() => {
document.documentElement.setAttribute('data-theme', theme);
}, [theme]);
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => useContext(ThemeContext);
The useEffect
hook is used to update the HTML attribute (data-theme
) whenever the theme changes.
Toggle Dark Mode in Components:
Now, you can use the useTheme
hook in any component to access the current theme and the toggleTheme
function.
jsx// components/SomeComponent.js
import { useTheme } from '../path-to/themes';
const SomeComponent = () => {
const { theme } = useTheme();
return (
<div className={`some-component ${theme}`}>
{/* Component content */}
</div>
);
};
export default SomeComponent;
In the above example, the component's class name is dynamically set based on the current theme.
By following these steps, you should have a working dark mode implementation in your Next.js application that persists the user's preference using local storage.