Home > Mobile >  change website theme after using switch from component OTHER than App.js react
change website theme after using switch from component OTHER than App.js react

Time:12-29

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.

  1. use useContext to save the theme value and call in App.js

  2. 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;
}
  • Related