ilokesto

Introduction

React state hooks backed by an external store.

@ilokesto/state

@ilokesto/state is the React-facing layer on top of @ilokesto/store. It does not invent a new state container. Instead, it takes an external store model and gives you a hook API that fits naturally into React through useSyncExternalStore.

That framing matters because it explains most of the package in one sentence: the store stays outside React, while reads and subscriptions are expressed as hooks.

What this package gives you

  • A single create() entry point for turning state or a vanilla store into a React hook.
  • Two usage modes: plain state mode and reducer mode.
  • Selector-based subscriptions that keep reads narrow.
  • Imperative accessors like writeOnly() for actions outside components.
  • Composable store-level middleware for logging, persistence, validation, and debugging.

What it intentionally does not give you

  • No provider-first architecture.
  • No Zustand-style initializer function.
  • No separate custom equality API for selectors.
  • No attempt to hide that there is a real store under the hook.

Installation

npm install @ilokesto/state

Quick Look

import { create } from '@ilokesto/state';

const useCounter = create({ count: 0 });

function Counter() {
  const [count, setState] = useCounter((state) => state.count);

  return (
    <button onClick={() => setState((prev) => ({ ...prev, count: prev.count + 1 }))}>
      {count}
    </button>
  );
}

This small example already shows the core shape:

  • create() builds a hook from external state,
  • the selector decides what the component reads,
  • the writer still updates the full store state.

If you are new to the package, start with Quick Start.

  • Read Mental Model if you want to understand why the store lives outside React.
  • Read Selectors if the selector/writer split is the part that still feels strange.
  • Read Existing Store if you already own a vanilla Store and only need the React binding layer.

On this page