npm package: @liderbektas/lite-context
Description: A lightweight, type-safe state management solution for React. Built on Context and useSyncExternalStore, it delivers selective re-rendering with zero dependencies — all under 1KB.
Author: liderbektas
Latest version: 0.1.3

# @liderbektas/lite-context

A lightweight, type-safe state management solution for React.  
Built on `Context` + `useSyncExternalStore` — selective re-rendering with zero dependencies, all under 1KB.

[![npm version](https://img.shields.io/npm/v/@liderbektas/lite-context.svg)](https://www.npmjs.com/package/@liderbektas/lite-context)
[![bundle size](https://img.shields.io/bundlephobia/minzip/@liderbektas/lite-context)](https://bundlephobia.com/package/@liderbektas/lite-context)
[![license](https://img.shields.io/npm/l/@liderbektas/lite-context.svg)](https://github.com/liderbektas/lite-context/blob/main/LICENSE)

## The Problem

React Context re-renders **every** consumer when state changes — even if the value they care about hasn't changed. In a real app, this means updating a single field can trigger re-renders across dozens of unrelated components.

`@liderbektas/lite-context` fixes this. Components only re-render when the **specific slice** they subscribe to changes.

## Installation

```bash
npm install @liderbektas/lite-context
```

> Requires React 18+

## Examples

### Object Store

```tsx
import createLiteContext from "@liderbektas/lite-context";

interface AuthState {
  user: string | null;
  role: "admin" | "viewer";
  lastLogin: Date | null;
}

const { Provider: AuthProvider, useStore: useAuth } =
  createLiteContext<AuthState>({
    user: null,
    role: "viewer",
    lastLogin: null,
  });

// Only re-renders when `user` changes — ignores role and lastLogin updates
function Greeting() {
  const [user] = useAuth((s) => s.user);
  return <h1>Welcome, {user ?? "Guest"}</h1>;
}

// Write-only — never re-renders from store changes
function LoginButton() {
  const [, setAuth] = useAuth(() => null);

  return (
    <button
      onClick={() =>
        setAuth((s) => ({ ...s, user: "Jane", lastLogin: new Date() }))
      }
    >
      Sign in
    </button>
  );
}

function App() {
  return (
    <AuthProvider>
      <Greeting />
      <LoginButton />
    </AuthProvider>
  );
}
```

### Array Store

```tsx
import createLiteContext from "@liderbektas/lite-context";

interface Todo {
  id: number;
  text: string;
  done: boolean;
}

const { Provider: TodoProvider, useStore: useTodos } = createLiteContext<Todo[]>([
  { id: 1, text: "Ship lite-context", done: true },
  { id: 2, text: "Write docs", done: false },
  { id: 3, text: "Celebrate", done: false },
]);

// Only re-renders when THIS specific todo changes
function TodoItem({ id }: { id: number }) {
  const [todo] = useTodos((s) => s.find((t) => t.id === id));
  const [, setTodos] = useTodos(() => null);

  if (!todo) return null;

  return (
    <label style={{ textDecoration: todo.done ? "line-through" : "none" }}>
      <input
        type="checkbox"
        checked={todo.done}
        onChange={() =>
          setTodos((prev) =>
            prev.map((t) => (t.id === id ? { ...t, done: !t.done } : t))
          )
        }
      />
      {todo.text}
    </label>
  );
}

function App() {
  return (
    <TodoProvider>
      {[1, 2, 3].map((id) => (
        <TodoItem key={id} id={id} />
      ))}
    </TodoProvider>
  );
}
```

Toggling todo #2 **only re-renders that item** — the rest stay untouched.

## API

### `createLiteContext<T>(initialState: T)`

Returns `{ Provider, useStore }`.

### `useStore(selector)`

```tsx
const [value, setState] = useStore((store) => store.someField);
```

| Return     | Description                                                           |
| ---------- | --------------------------------------------------------------------- |
| `value`    | Selected slice of state. Component re-renders only when this changes. |
| `setState` | Updater function. Receives current state, must return the next state. |

**Write-only pattern** — pass `() => null` as selector to get a setter without subscribing to any changes.

## Comparison

| Feature             | @liderbektas/lite-context | React Context | Zustand | Jotai    |
| ------------------- | ------------------------- | ------------- | ------- | -------- |
| Bundle size         | ~1KB                      | 0 (built-in)  | ~1.5KB  | ~2.5KB   |
| Selective re-render | ✅                        | ❌            | ✅      | ✅       |
| Zero dependencies   | ✅                        | ✅            | ✅      | ✅       |
| TypeScript          | ✅                        | ✅            | ✅      | ✅       |
| Devtools            | ❌                        | ❌            | ✅      | ✅       |
| Middleware          | ❌                        | ❌            | ✅      | ✅       |
| Context-based       | ✅                        | ✅            | ❌      | ❌       |
| Learning curve      | Minimal                   | Minimal       | Low     | Moderate |

## License

[MIT](./LICENSE)