Maintaining a Simple Global State Store in React Without Extra Libraries

By : manish

Language: javascript

Date Published: 4 days, 3 hours ago

For many mid‑size frontends, you do not need Redux or heavy state libraries to manage global state. A simple combination of React Context and a single store hook is often enough for things like auth, theme, and user preferences. The idea is to keep most state local to components and lift only truly shared data into a lightweight global store. This keeps components easier to reason about, avoids prop‑drilling, and reduces unnecessary dependencies.

A practical pattern is: create a context, use a provider at the app root, and expose a custom hook like useAppStore for reading and updating shared state. Keep the store shape small and focused on stable, long‑lived values (e.g., user, theme, isSidebarOpen). For more dynamic data (like server lists), prefer data‑fetching hooks per screen. This approach scales well for typical dashboards, support tools, or e‑commerce consoles without over‑engineering.


 

Style : Dark Mode : Line Number: Download Font Size:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// store/AppStore.tsx
import React, { createContext, useContext, useState, ReactNode } from "react";

type Theme = "light" | "dark";

type AppState = {
  theme: Theme;
  user: { id: string; name: string } | null;
  isSidebarOpen: boolean;
};

type AppStore = AppState & {
  setTheme: (theme: Theme) => void;
  setUser: (user: AppState["user"]) => void;
  toggleSidebar: () => void;
};

const AppStoreContext = createContext<AppStore | null>(null);

export function AppStoreProvider({ children }: { children: ReactNode }) {
  const [theme, setTheme] = useState<Theme>("light");
  const [user, setUser] = useState<AppState["user"]>(null);
  const [isSidebarOpen, setIsSidebarOpen] = useState(true);

  const toggleSidebar = () => setIsSidebarOpen((prev) => !prev);

  const value: AppStore = {
    theme,
    user,
    isSidebarOpen,
    setTheme,
    setUser,
    toggleSidebar,
  };

  return (
    <AppStoreContext.Provider value={value}>
      {children}
    </AppStoreContext.Provider>
  );
}

export function useAppStore() {
  const ctx = useContext(AppStoreContext);
  if (!ctx) {
    throw new Error("useAppStore must be used within AppStoreProvider");
  }
  return ctx;
}

// App.tsx – wrap your app once
/*
import { AppStoreProvider } from "./store/AppStore";

export default function AppRoot() {
  return (
    <AppStoreProvider>
      <App />
    </AppStoreProvider>
  );
}
*/

// Any component can now read/update global state

// components/Header.tsx
import { useAppStore } from "../store/AppStore";

export function Header() {
  const { user, theme, setTheme, toggleSidebar } = useAppStore();

  return (
    <header className="header">
      <button onClick={toggleSidebar}></button>
      <h1>Dashboard</h1>
      <div className="spacer" />
      <button
        onClick={() => setTheme(theme === "light" ? "dark" : "light")}
      >
        Theme: {theme}
      </button>
      {user ? (
        <span className="user">Hi, {user.name}</span>
      ) : (
        <button>Sign in</button>
      )}
    </header>
  );
}
react state-management context frontend global-state
Login to see the comments