Comments (9)
In my case, I have 2 theme providers where one is forced and one is not forced. And in App Router, we can use the grouping folder (group1) and (group2).
Put the non forced in (group1) folder and forced one inside the layout of (group2) folder. In this case, the layouts will affects only the pages inside each own groups.
from next-themes.
That was my case, but I suppose you can set resolvedTheme to a useRef and then just pass it when unmounting the component.
Open two pages, one with the light theme and one with your implementation of forced dark. Opening the dark theme page will change the theme of the first one.
Also selecting any theme on the main website theme selector will change the dark theme page.
You're right. Sorry, I just covered my very narrow use-case.
What I ended up doing, however, is what is described here. That works fine with Tailwind because I can set the dark specifier on the inner component. It works correctly in multiple tabs as well. However, if it's important for you, this won't change resolvedTheme
, as pointed out.
from next-themes.
I have 1 page that needs to be with a forced theme
having two global folders looks too much in this case
from next-themes.
I made a provider like this
But it doesn't solve the problem completely, for a second when loading the original theme appears
"use client"
import * as React from "react";
import { ThemeProvider as NextJSThemesProvider } from "next-themes";
import { ThemeProviderProps as NextJSThemesProviderProps } from "next-themes/dist/types";
interface ForcedThemeContextProps {
forcedTheme: string | null;
setForcedTheme: React.Dispatch<React.SetStateAction<string | null>>;
}
const ForcedThemeContext = React.createContext<ForcedThemeContextProps | undefined>(undefined);
export function useForcedThemeControl(): ForcedThemeContextProps {
const context = React.useContext(ForcedThemeContext);
if (!context) {
throw new Error("useForcedThemeControl must be used within a ForcedThemeContextProvider");
}
return context;
}
interface ForcedThemeContextProviderProps {
children: React.ReactNode;
}
export function ForcedThemeContextProvider({ children }: ForcedThemeContextProviderProps): JSX.Element {
const [forcedTheme, setForcedTheme] = React.useState<string | null>(null);
return (
<ForcedThemeContext.Provider value={{ forcedTheme, setForcedTheme }}>
{children}
</ForcedThemeContext.Provider>
);
}
interface ThemeSetterProps {
children: React.ReactNode;
}
function DarkTheme({ children }: ThemeSetterProps): JSX.Element {
const { setForcedTheme } = useForcedThemeControl();
React.useEffect(() => {
setForcedTheme("dark");
}, []);
return <>{children}</>;
}
function LightTheme({ children }: ThemeSetterProps): JSX.Element {
const { setForcedTheme } = useForcedThemeControl();
React.useEffect(() => {
setForcedTheme("light");
}, []);
return <>{children}</>;
}
interface CombinedThemeProviderProps extends NextJSThemesProviderProps {
children: React.ReactNode;
}
const CombinedThemeProvider = ({ children, ...props }: CombinedThemeProviderProps): JSX.Element => {
const { forcedTheme } = useForcedThemeControl();
return (
<NextJSThemesProvider {...props} forcedTheme={forcedTheme || undefined}>
{children}
</NextJSThemesProvider>
);
};
function ThemeProvider({ children, ...props }: CombinedThemeProviderProps): JSX.Element {
return (
<ForcedThemeContextProvider>
<CombinedThemeProvider {...props}>
{children}
</CombinedThemeProvider>
</ForcedThemeContextProvider>
);
}
export {
ThemeProvider,
LightTheme,
DarkTheme
}
from next-themes.
I was facing the same problem. Creating route segments would be enough, but I wanted to avoid this as I also had only one page with forced theme.
The solution I came up with was the following:
- Create a
DarkModeWrapper
client component:
"use client";
import { useTheme } from "next-themes";
import { useEffect } from "react";
export function DarkModeWrapper({ children }: { children: React.ReactNode }) {
const { setTheme } = useTheme();
useEffect(() => {
setTheme("dark");
return () => {
setTheme("light");
};
}, []);
return children;
}
- Wrap the desired page with it:
import { DarkModeWrapper } from "@/components/common/DarkModeWrapper";
export default Page = () => {
return (
<DarkModeWrapper>
<h1>Hello Dark Mode</h1>
</DarkModeWrapper>
);
};
from next-themes.
Isn't setTheme
setting theme globally?
In this case, your local wrapper is affecting the whole website
setTheme("dark");
return () => {
setTheme("light");
};
}, []);
This code will make the dark theme on one page but will set the light theme for other pages even if the dark theme is selected there.
from next-themes.
Isn't
setTheme
setting theme globally?In this case, your local wrapper is affecting the whole website
setTheme("dark"); return () => { setTheme("light"); }; }, []);
This code will make the dark theme on one page but will set the light theme for other pages even if the dark theme is selected there.
That was my case, but I suppose you can set resolvedTheme
to a useRef
and then just pass it when unmounting the component.
from next-themes.
That was my case, but I suppose you can set resolvedTheme to a useRef and then just pass it when unmounting the component.
Open two pages, one with the light theme and one with your implementation of forced dark.
Opening the dark theme page will change the theme of the first one.
Also selecting any theme on the main website theme selector will change the dark theme page.
from next-themes.
I solved this in a hacky way: using usePathname()
in a client component, then determining whether the theme should be forced based on some regex matching for specific paths. Then, I passed the forced theme to the ThemeProvider
. Pseudo code example here:
"use client"
import { usePathname } from 'next/navigation'
import { ThemeProvider } from 'next-themes'
export const Providers = (props) => {
const pathname = usePathname();
const forcedThemeFromPathname = pathname === "/dark-only" ? "dark" : undefined;
return (
<ThemeProvider forcedTheme={forcedThemeFromPathname}>
{props.children}
</ThemeProvider>
)
}
I'd like to find a better solution but so far I've got nothing. We need a way to pass information up from a page.tsx
(server component) file to the root layout.
from next-themes.
Related Issues (20)
- `resolvedTheme` does not resolve to `dark` | `light` but instead to `system` HOT 1
- Support for multiple attributes (more in depth theme management)
- Flash of no theme (zero-config ThemeProvider, Next 14, not Cloudflare) HOT 1
- setTheme does not update DOM (next 13) HOT 1
- How can I get a transition between dark and light mode HOT 4
- defaultTheme did't work in the latest Chrome for macOS HOT 7
- Next Themes Flash of White BG when using the basePath HOT 4
- Inconsistent theming when the page loads HOT 3
- light/dark mode by changing class names on html tag HOT 2
- There is a error while setting up ThemeProvider HOT 5
- How to disable syncing themes between tabs HOT 2
- Documentation out of date with Tailwind's new dark-mode API
- Should `resolvedTheme` obey `forcedTheme`? HOT 3
- Allow nested providers HOT 2
- Theme object is injected into the "data-theme" property. HOT 1
- useTheme doesn't work in monorepo ui library. HOT 1
- `TypeError: Cannot read properties of undefined (reading 'addListener')` using `vitest`/`@testing-library/react` HOT 1
- Support for changing both class and data-theme attribute simultaneously HOT 1
- Callback Version of `setTheme` Passes Itself HOT 1
- Possibility to share across sub-domains? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from next-themes.