Reputation: 137
I have two CSS files one for Light theme and other for Dark theme. How to dynamically change the style sheets ?
import React, { useState, useEffect } from "react";
import "../styles/globals.css";
import "primereact/resources/primereact.min.css";
import "primeicons/primeicons.css";
import { ThemeContext } from "../context/ThemeContext";
function MyApp({ Component, pageProps }) {
const [theme, setTheme] = useState("light");
useEffect(() => {
if (theme == "dark") {
import("primereact/resources/themes/arya-blue/theme.css");
}
if (theme == "light") {
import("primereact/resources/themes/saga-blue/theme.css");
}
}, [theme]);
return (
<ThemeContext.Provider value={[theme, setTheme]}>
<Component {...pageProps} />
</ThemeContext.Provider>
);
}
export default MyApp;
This code is working to switch from light theme to dark theme but it fails to switch from dark to light. Is their any better way to do this ?
Upvotes: 5
Views: 7538
Reputation: 137
I solved this problem by this blog post with some differences.
const DarkTheme = () => {
return (
<style jsx global>
{`
Copied here the entire dark mode style sheet from node modules (around 5000 lines)
`}
</style>
);
};
const LightTheme = () => {
return (
<style jsx global>
{`
Copied here the entire light mode style sheet from node modules (around 5000 lines)
`}
</style>
);
};
export default function Theme({ theme }) {
if (theme == "dark") {
return <DarkTheme />;
}
return <LightTheme />;
}
import React, { useState, useEffect } from "react";
import Head from "next/head";
import "../styles/globals.css";
import "primereact/resources/primereact.min.css";
import "primeicons/primeicons.css";
import { ThemeContext } from "../context/ThemeContext";
import Theme from "../themes/Theme"; //imported newly created theme file
import PrimeReact from "primereact/api";
function MyApp({ Component, pageProps }) {
const [theme, setTheme] = useState((typeof window !== "undefined" && localStorage.getItem("theme")) || "light");
useEffect(() => {
typeof window !== "undefined" && localStorage.setItem("theme", theme);
}, [theme]);
return (
<>
<ThemeContext.Provider value={[theme, setTheme]}>
<Theme theme={theme} /> {//This Component provides dynamic global styles}
<Component {...pageProps} />
</ThemeContext.Provider>
</>
);
}
export default MyApp;
Upvotes: 4
Reputation: 485
The problem is that when switching back to light
theme from dark
theme your app contains the css of both dark
and light
themes.
One solution that comes to my mind is to store the theme state in local storage and then reload the page , something like this
Although it has a drawback that upon theme change your website would lose all the other states
import React, { useState, useEffect } from "react";
import "../styles/globals.css";
import "primereact/resources/primereact.min.css";
import "primeicons/primeicons.css";
import { ThemeContext } from "../context/ThemeContext";
function MyApp({ Component, pageProps }) {
const [theme, setTheme] = useState("light");
const currentTheme = localStorage.getItem("theme");
useEffect(() => {
localStorage.setItem("theme",theme)
window.location.reload();
}, [theme]);
if (currentTheme == "dark") {
import("primereact/resources/themes/arya-blue/theme.css");
}
if (currentTheme == "light") {
import("primereact/resources/themes/saga-blue/theme.css");
}
return (
<ThemeContext.Provider value={[theme, setTheme]}>
<Component {...pageProps} />
</ThemeContext.Provider>
);
}
export default MyApp;
Upvotes: 3