React - what is the proper way to do global state?

Viewed 12764

I have here an app, and I want the App component to hold the current logged in user. I have the following routes and components.

Basically, every component in my app will make use of the user object. Sure I can pass the user as props to each and every component, but that is not elegant. What is the proper React way of sharing the user prop globally?

const App = () => {
    const [user, setUser] = useState(null);

    return (
        <Router>
            <div className="app">
                <Topbar />
                <Switch>
                    <Route path="/login" exact component={Login} />
                    <Route path="/home" exact component={Home} />
                    <Route path="/" exact component={ShopMenu} />
                    <Route path="/orders">
                        <Orders />
                    </Route>
                    <Route path="/wishlist" exact component={Wishlist} />
                    <Route path="/wallet" exact component={Wallet} />
                    <Route path="/cart" exact component={Cart} />
                </Switch>
                <BottomBar />
            </div>
        </Router>
    );
};
2 Answers

Take a look at React Context and more specifically useContext as you're using hooks.

The idea of context is exactly that - for you to be able to share updateable state to the descendants without having to pass it from component to component.

const UserContext = React.createContext(null);

const App = () => {
  const [user, setUser] = useState(null);

  return (
    <Router>
      <div className="app">
        <UserContext.Provider value={user}>
          <Topbar />
          <Switch>
            <Route path="/login" exact component={Login} />
            <Route path="/home" exact component={Home} />
            <Route path="/" exact component={ShopMenu} />
            <Route path="/orders">
              <Orders />
            </Route>
            <Route path="/wishlist" exact component={Wishlist} />
            <Route path="/wallet" exact component={Wallet} />
            <Route path="/cart" exact component={Cart} />
          </Switch>
          <BottomBar />
        </UserContext.Provider>
      </div>
    </Router>
  );
};

Then, in your component:

const Topbar = () => {
  const user = useContext(UserContext);

  // use `user` here
};

If you want to have access to the setter (setUser) you can pass it through the context as well.

Related