I am new to react. I am trying to change the entire theme of the website by using a switch that is inside a component called NavBar.js. All of the youtube videos, tutorials, and websites that I have found are basically teaching me how to script the theme change within the App.js file, but I want to change the entire theme from this file called NavBar.js because that is where the switch is.
Essentially if a user toggles the theme switch within the NavBar component, it changes the theme entirely. So far I am just able to change the background of the body, but I want to change the background on other components (as well as modify their text colors etc.). This code only changes the background of the main body. Could I just have some direction on what I would need to do to accomplish this? Could I just switch CSS style sheets?
export default function NavBar(){
const[theme, setTheme] = useState('dark');
const toggleTheme = () => {
setTheme((theme) => (theme === 'dark' ? 'light' : 'dark'));
if(theme === 'dark')
{
document.body.style = 'background: red;';
}
else{
document.body.style = 'background: white;';
}
}
return(
<div className="main-container">
<div>
<Link to="home"><img src={logo} alt="logo" className="nav-icon"/></Link>
</div>
<div className='theme-Switch-container'>
<Switch onChange={toggleTheme}/>
<h4 style={{position: 'relative', display: 'inline'}}>Switch Theme</h4>
</div>
<div>
<NavbarOption icon={searchGlass} alt="search icon" option="Explore"/>
<NavbarOption icon={bell} alt="bell icon" option="Notifications"/>
<NavbarOption icon={profile} alt="profile icon" option="Profile" link="profile"/>
<NavbarOption icon={forums} alt="forum icon" option="Forums"/>
<NavbarOption icon={market} alt="market icon" option="Cybermarket"/>
<NavbarOption icon={livestream} alt="livestream icon" option="Livestream"/>
<NavbarOption icon={analytics} alt="analytics icon" option="Analytics"/>
<NavbarOption icon={gear} alt="gear icon" option="Settings"/>
<NavbarOption icon={help} alt="help icon" option="Help"/>
{/* <Link to="" className="PostBtn">Post</Link> */}
<button className="PostBtn">Post</button>
{/* <div className="PostBtn">
<h3>Post</h3>
</div> */}
</div>
</div>
);
}
CodePudding user response:
A nice way to solve this issue will be either using redux or useContext API. I would go for useContext to keep it simple.
In your App.js you can set the context like this:
const ThemeContext = createContext(null); // keep in mind that you can set anything to creatContext as default values.
export default function MyApp() {
return (
<ThemeContext.Provider value="dark">
<NavBar/>
// add more components here that can use the default colors
</ThemeContext.Provider>
)
}
and then in any of your components you can consume/use the useContext like this:
function Panel({ title, children }) {
const theme = useContext(ThemeContext);
const className = 'panel-' theme;
return (
<section className={className}>
<h1>{title}</h1>
{children}
</section>
)
}
function Button({ children }) {
const theme = useContext(ThemeContext);
const className = 'button-' theme;
return (
<button className={className}>
{children}
</button>
);
}
You can read more about useContext API from here useContext
Hope that helps!
CodePudding user response:
There is two way to do.
use useContext to save the theme value and call in App.js
set a state in App.js and change state in NavBar.js
Way 2 would be like:
app.js
const[theme, setTheme] = useState('dark');
...
<NavBar theme={theme} setTheme={setTheme} .../>
...
NavBar.js
function NavBar(props){
const {theme,setTheme} = props
const toggleTheme = () => {
setTheme((theme) => (theme === 'dark' ? 'light' : 'dark'));
if(theme === 'dark')
{
document.body.style = 'background: red;';
}
else{
document.body.style = 'background: white;';
}
}
...
CodePudding user response:
add a css class to the body to save the theme state like dark
and in your css file(s), use body.dark
selector to listen to theme changes.
const toggleTheme = () => {
setTheme((theme) => (theme === 'dark' ? 'light' : 'dark'));
document.body.classList.toggle("dark");
}
in css try something like:
body.dark {
background-color: red;
}
body.dark /* any component css class name here */ {
background-color: red;
}