one-global-state
v1.3.0
Published
Lightweight React global state hook — useGlobalState()
Maintainers
Readme
one-global-state
A tiny React hook that gives you useState-style API with automatic global sync across all components — no Context, no Provider, no prop drilling.
Installation
npm install one-global-stateQuick start
import { useGlobalState } from "one-global-state";
function Counter() {
const [count, setCount] = useGlobalState("count", 0);
return <button onClick={() => setCount((n) => n + 1)}>Count: {count}</button>;
}Any component that calls useGlobalState with the same key will share the same value and re-render whenever it changes.
API
useGlobalState<T>(key, initialValue)
const [value, setValue] = useGlobalState<T>(key: string, initialValue: T)| Param | Type | Description |
| -------------- | -------- | --------------------------------------------- |
| key | string | Unique identifier for the global state entry |
| initialValue | T | Used only if no value exists for this key yet |
Returns [value, setValue] — identical shape to useState.
setValue accepts both a direct value and a functional updater:
setValue(42); // direct value
setValue((prev) => prev + 1); // functional updatersetGlobalState<T>(key, value) — standalone setter
Update global state from outside a React component (event handlers, utils, etc.):
import { setGlobalState } from "one-global-state";
setGlobalState("count", 0); // direct value
setGlobalState("count", (n) => n + 1); // functional updaterUsage examples
Multiple components sharing one key
function CounterDisplay() {
const [count] = useGlobalState("count", 0);
return <span>{count}</span>;
}
function CounterControls() {
const [, setCount] = useGlobalState("count", 0);
return (
<>
<button onClick={() => setCount((n) => n - 1)}>−</button>
<button onClick={() => setCount((n) => n + 1)}>+</button>
<button onClick={() => setCount(0)}>Reset</button>
</>
);
}Both components stay in sync automatically — no shared parent state needed.
Multiple independent keys
function Profile() {
const [name, setName] = useGlobalState("username", "");
const [theme, setTheme] = useGlobalState<"light" | "dark">("theme", "light");
return (
<>
<input value={name} onChange={(e) => setName(e.target.value)} />
<button
onClick={() => setTheme((t) => (t === "light" ? "dark" : "light"))}
>
Toggle theme
</button>
</>
);
}Array state with functional updater
type Todo = { id: number; text: string; done: boolean };
function useTodos() {
return useGlobalState<Todo[]>("todos", []);
}
function AddTodo() {
const [, setTodos] = useTodos();
const add = (text: string) =>
setTodos((prev) => [...prev, { id: Date.now(), text, done: false }]);
// ...
}
function TodoList() {
const [todos, setTodos] = useTodos();
const toggle = (id: number) =>
setTodos((prev) =>
prev.map((t) => (t.id === id ? { ...t, done: !t.done } : t)),
);
// ...
}Calling setGlobalState outside React
// Reset all state on logout — no hook needed
function logout() {
setGlobalState("username", "");
setGlobalState("todos", []);
}Production Use Case
to avoid dealing with all unique keys management, it will be better to wrap each global state inside a custom hook.
For example, if we want to store a global filter for a table which is displaying the data as per the filter set, we can use something like below
//GLOBAL CONSTS
const FILTER_KEY = "filter-key";
function useGlobalFilter() {
return useGlobalState<FilterSettings>(FILTER_KEY, {
order: "desc",
sort: "name",
});
}Then use the useGlobalFilter where ever required inside the project.
How it works
- A module-level
Mapstores values keyed by string — shared across the entire app. - Built on
useSyncExternalStore, React's purpose-built API for external stores, ensuring tear-free re-renders under concurrent mode. - React is a peer dependency — the library ships zero runtime dependencies.
Requirements
- React ≥ 17 (uses
useSyncExternalStorevia React 18+; for React 17 add the shim)
License
MIT
