
Security News
vlt Launches "reproduce": A New Tool Challenging the Limits of Package Provenance
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
react-next-theme
Advanced tools
A simple and flexible theme switcher for React and Next.js, supporting light and dark modes with localStorage and system preferences.
react-next-theme
is a lightweight, customizable theme switcher for React and Next.js applications, supporting light and dark modes. It detects system preferences, applies the theme instantly, and prevents a white flash on page load.
Install the Package
npm install react-next-theme
or
yarn add react-next-theme
Create CSS for Theme Variables
Define theme colors in a CSS file. You can either create a theme.css
file in the public
folder or add these styles directly to index.css
(React) or globals.css
(Next.js).
/* Light and dark mode theme variables */
:root {
--background-color: white;
--text-color: black;
}
html[data-theme='dark'] {
--background-color: black;
--text-color: white;
}
body {
background-color: var(--background-color);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
}
Add Theme Script to public/index.html
To ensure the theme is applied before the app mounts, create a theme-script.js
file in the public
folder with the following code:
// public/theme-script.js
(function() {
const storedTheme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = storedTheme || (prefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
})();
Then, link the script in public/index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React App</title>
<!-- Link to theme initialization script -->
<script src="%PUBLIC_URL%/theme-script.js"></script>
<!-- Link to CSS file -->
<link rel="stylesheet" href="%PUBLIC_URL%/theme.css" />
</head>
<body>
<div id="root"></div>
</body>
</html>
Wrap Your App with ThemeProvider
in src/index.js
Wrap your main app component with ThemeProvider
to enable dynamic theme switching.
// src/index.js or src/main.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { ThemeProvider } from 'react-next-theme';
ReactDOM.render(
<ThemeProvider>
<App />
</ThemeProvider>,
document.getElementById('root')
);
Use the useTheme
Hook in Components
Use the useTheme
hook to toggle themes in any component. Here’s an example for a button in App.js
:
// src/App.js
import React from 'react';
import { useTheme } from 'react-next-theme';
function App() {
const { theme, toggleTheme } = useTheme();
return (
<div>
<h1>{theme === 'light' ? 'Light Mode' : 'Dark Mode'}</h1>
<button onClick={toggleTheme}>
{theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'}
</button>
</div>
);
}
export default App;
Theme Initialization Script in _document.js
To apply the theme before Next.js renders the app, you can either use getThemeScript
from react-next-theme
or link a separate script file.
Option A: Use getThemeScript
directly:
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document';
import { getThemeScript } from 'react-next-theme';
export default function Document() {
return (
<Html lang="en">
<Head>
<link rel="stylesheet" href="/theme.css" />
<script dangerouslySetInnerHTML={{ __html: getThemeScript() }} />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
Option B: Use an external script file:
Create public/theme-script.js
:
// public/theme-script.js
(function() {
const storedTheme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = storedTheme || (prefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
})();
Reference the script file in _document.js
:
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document';
import Script from 'next/script';
export default function Document() {
return (
<Html lang="en">
<Head>
<link rel="stylesheet" href="/theme.css" />
</Head>
<body>
<Script src="/theme-script.js" strategy="beforeInteractive" />
<Main />
<NextScript />
</body>
</Html>
);
}
Wrap Your App with ThemeProvider
in _app.js
Wrap the main component with ThemeProvider
to handle theme switching:
// pages/_app.js
import { ThemeProvider } from 'react-next-theme';
function MyApp({ Component, pageProps }) {
return (
<ThemeProvider>
<Component {...pageProps} />
</ThemeProvider>
);
}
export default MyApp;
Theme Initialization in app/layout.js
In Next.js 13+ (App Router), you can initialize the theme by either using getThemeScript
or an external script file.
Option A: Use getThemeScript
directly:
// app/layout.js
import { ThemeProvider, getThemeScript } from 'react-next-theme';
export const metadata = {
title: 'My App',
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<link rel="stylesheet" href="/theme.css" />
<script dangerouslySetInnerHTML={{ __html: getThemeScript() }} />
</head>
<body>
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
);
}
Option B: Use an external script file:
Create public/theme-script.js
as follows:
// public/theme-script.js
(function() {
const storedTheme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = storedTheme || (prefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
})();
Reference the script file in app/layout.js
:
// app/layout.js
import { ThemeProvider } from 'react-next-theme';
import Script from 'next/script';
export const metadata = {
title: 'My App',
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<link rel="stylesheet" href="/theme.css" />
</head>
<body>
<Script src="/theme-script.js" strategy="beforeInteractive" />
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
);
}
useTheme
Hook to Toggle ThemesTo toggle themes in components, use the useTheme
hook.
// components/Header.js
import { useTheme } from 'react-next-theme';
function Header() {
const { theme, toggleTheme } = useTheme();
return (
<header>
<button onClick={toggleTheme}>
{theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'}
</button>
</header>
);
}
export default Header;
For simplicity and a clean setup, using getThemeScript
is often the best choice, especially for projects where ease of integration and minimal file management are priorities. It’s also ideal for teams that prefer not to have extra files in public
or are working on smaller projects.
However, for larger projects or production-level apps where caching and modularity are important, using public/theme-script.js
can improve load times slightly and centralize your theme logic.
In summary:
getThemeScript
public/theme-script.js
Let me know if you’d like further customization in setup based on these considerations!
If you prefer to use an external script file, you can place the theme initialization script inside the public/
folder and reference it using the <Script>
component in Next.js:
public/theme-script.js
:// public/theme-script.js
(function() {
const storedTheme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = storedTheme || (prefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
})();
_document.js
or layout.js
import Script from 'next/script';
<Script src="/theme-script.js" strategy="beforeInteractive" />
This will load the theme initialization script from the public/
directory.
MIT License
Feel free to modify or contribute to the project. Happy coding!
FAQs
A simple and flexible theme switcher for React and Next.js, supporting light and dark modes with localStorage and system preferences.
The npm package react-next-theme receives a total of 0 weekly downloads. As such, react-next-theme popularity was classified as not popular.
We found that react-next-theme demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
Research
Security News
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
Research
The Socket Research Team discovered a malicious npm package, '@ton-wallet/create', stealing cryptocurrency wallet keys from developers and users in the TON ecosystem.