Search code examples
reactjsreact-router

Global variable / state in React (with React router)


I am new to React and trying to build a website with dark mode.

by changing the data-theme in CSS file when the toggle button is clicked, and the following is my file structure in App.jsx.

├── Header
│   └── DarkModeToggle
├── Content
│
└── (CSS file)

DarkModeToggle.jsx

class NightModeToggle extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            theme: 'light',
        }
        this.toggleTheme = this.toggleTheme.bind(this);
    }

    toggleTheme() {
        const theme = this.state.theme === 'dark' ? 'light' : 'dark';
        this.setState({ theme });
        document.documentElement.setAttribute("data-theme", theme);
    }

    render() {...}
}

I also use react route so that I can display different information in different URL

Content.jsx

class Content extends React.Component {
    render() {
        return (
            <div id="content">
                <BrowserRouter>
                    <Switch>
                        <Route exact path='/test' component={Test}></Route>
                        <Route exact path='/home' component={Home}></Route>
                        <Route exact path='/project' component={Project}></Route>
                    </Switch>
                </BrowserRouter>
            </div>
        );
    }
}

However, the website cannot keep the theme when I go to other URL.

For example, I change to dark mode in /home and then I go to /project, the website will back to the light mode.

How can I maintain the theme variable (or init a global variable) when I using React-Route? Thank you for your help!


Solution

  • You can use Context API from react to create global context.
    Then you can wrap your app file within context you have created.
    Now you can access themeMode from any file inside react render tree.


    Below is example, how you can use themeMode with context API

    Context

    import React, { createContext, useState } from "react";
    
    export const AppContext = createContext();
    
    const AppProvider = ({ children }) => {
      const [themeMode, setThemeMode] = useState("lightTheme");
    
      const value = { themeMode };
    
      return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
    };
    
    export default AppProvider;
    
    

    Index

    
    import React from "react";
    import ReactDOM from "react-dom";
    import App from "./App";
    import AppProvider from "./AppProvider";
    
    ReactDOM.render(
      <AppProvider>
        <App />
      </AppProvider>,
      document.getElementById("root")
    
    

    App

    import React, { useContext } from "react";
    import { AppContext } from "./AppProvider";
    
    const App = () => {
      const { themeMode } = useContext(AppContext);
      console.log("THEME MODE: ", themeMode);
      return <div></div>;
    };
    
    export default App;