npm package: @sazzadur/react-store
Description: A simple and efficient React hook for managing state with context and localStorage support.
Author: Sazzadur Rahman
Latest version: 1.1.1

# @sazzadur/react-store

A simple, lightweight global state solution for React using Context and hooks — with optional `localStorage` persistence and a built-in loading state.

No reducers. No boilerplate. Just state.

---

## ✨ Why this exists

Most state management solutions are either:

-   too heavy for small to medium apps, or
-   too opinionated for simple shared state

`@sazzadur/react-store` is designed for cases where you want:

-   a global store without complexity
-   minimal and predictable API
-   full TypeScript inference
-   safe usage with Next.js and client components

---

## 📦 Installation

```bash
npm install @sazzadur/react-store
```

or

```bash
pnpm add @sazzadur/react-store
```

---

## 🧠 Core concept

-   A single global store is maintained using React Context
-   Each store value is accessed by a unique key
-   Components re-render only when their subscribed key changes
-   Values can optionally persist to `localStorage`
-   A `loading` state indicates when the value is still initializing

---

## 🚀 Getting started

### 1️⃣ Wrap your app with `StoreProvider`

```tsx
import { StoreProvider } from "@sazzadur/react-store";

export function App({ children }) {
	return <StoreProvider>{children}</StoreProvider>;
}
```

> In Next.js (App Router), wrap this inside a client component.

---

### 2️⃣ Use the store anywhere

```tsx
import { useStore } from "@sazzadur/react-store";

function Counter() {
	const [count, setCount, loading] = useStore("count", 0);

	if (loading) {
		return <p>Loading...</p>;
	}

	return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
```

---

## 🔁 `useStore` API

### Signature

```ts
const [value, setValue, loading] = useStore<T>(
  key: string,
  initialValue: T,
  storeInLocalStorage?: boolean
);
```

---

### Parameters

1. **key** (`string`)
   Unique identifier for the store value.

2. **initialValue** (`T`)
   Default value used before the store is initialized.

3. **storeInLocalStorage** (`boolean`, optional)
   Controls whether the value should be stored in `localStorage`.
   Defaults to `true`.

---

### Return values

`useStore` returns a tuple with **three values**:

1. **value**
   The current value from the global store.

2. **setValue**
   A function to update the value.

3. **loading**
   A boolean indicating whether the value is still being initialized
   (for example, while restoring from `localStorage`).

---

## 💾 localStorage persistence

### Default behavior (enabled)

```tsx
const [theme, setTheme, loading] = useStore("theme", "light");
```

-   Value is saved to `localStorage`
-   Restored automatically on reload

---

### Disable persistence

```tsx
const [tempValue, setTempValue, loading] = useStore("temp", "", false);
```

-   Value exists only in memory
-   Nothing is written to `localStorage`

---

## 🛡 Type safety

TypeScript infers types from the initial value:

```tsx
const [age, setAge] = useStore("age", 18);
// age is inferred as number
```

No `any`. No manual generics required.

or specify for more complex types:

```tsx
interface User {
	id: number;
	name: string;
}
const [user, setUser] = useStore<User | null>("user", null);
```

---

## 🧩 Multiple store values

```tsx
const [user, setUser, userLoading] = useStore("user", null);
const [token, setToken] = useStore("token", "");
```

Each key is isolated and managed independently.

---

## ⚠️ Next.js & SSR notes

When using `localStorage` persistence in Next.js:

-   Always handle the `loading` state before rendering UI
-   This prevents hydration mismatches and UI flicker

---

## 🧪 Supported environments

-   ✅ React 18+
-   ✅ Next.js (App Router & Pages Router)
-   ✅ Vite
-   ✅ CRA

---

## 📄 License

MIT © Sazzadur Rahman