⚠️ Version 2.x introduces breaking changes compared to 1.x
See CHANGELOG.md for details.
for v1x see READMEv1.md
A minimal reactive state manager for React projects where you want simple shared state without overhead. This library provides a slice-based multiple store, context-driven state management API with built-in async support.
based on observable-store-light
-
Observer-based state updates Components automatically re-render when a subscribed value changes.
-
Works with React hooks Built around a simple
useStore(key)hook. -
Fully typed with TypeScript Strong typing for keys and values out of the box.
-
Supports multiple independent stores Create as many stores as you need — each one is fully isolated.
-
Tiny bundle size
-
Provider-based architecture optional, but recommended
npm install react-store-lightor
pnpm add react-store-lightThis library provides a slice-based, context-driven state management API with built-in async support.
Creates an isolated slice definition. Each slice owns its own store identity and can be instantiated multiple times.
- returns:
-
createStore (initData) - creates a store instance with uniq id for this slice.
- returns:
- store - store with api type IStore
- returns:
-
useState (key, [Context]) subscribes a component to a single store field by key.
- returns:
- analog [value, setValue] = React.useState
- features:
- key that was assigned during initialization will be used, you cannot change it
- returns:
-
useAsync (key, async callback, [Context]) - subscribes a component to a single async store field by key.
- returns:
- dispatch - runs asynchronous callback
- value - async store state type IAsync
- abort - abort the callback if the callback has not yet returned the result.
- features:
- key that was assigned during initialization will be used, you cannot change it
- async function callback signature like Promise callback
- (...custom args) => (store, resolve, reject) => void | Promise
- returns:
-
useStore ([Context]) - returns the store for imperative access.
- returns:
- store - store with api
- returns:
-
useReducer([Context]) - returns registered reducers
- returns:
- reducer is a function that describes a deterministic state transition. Reducers may mutate the store via its API instead of returning a new state. function reducer signature is:
- (...custom args) => (store) => void
- reducer is a function that describes a deterministic state transition. Reducers may mutate the store via its API instead of returning a new state. function reducer signature is:
- returns:
-
Creates a React Context.
- returns:
- Context - React Context optional used by:
- createSlice
- useState
- useAsync
- useStore
- Context - React Context optional used by:
Creates a Provider for injecting stores.
-
returns:
- Provider - Registers store instances in the React tree.
- props:
- children: ReactNode
- value: Store[]
- value — array of store instances
- props:
- Provider - Registers store instances in the React tree.
-
features:
- each store must have a unique uniqId
- duplicate stores will throw a runtime error
- asyncInit - сreates an initial async state
- asyncPending - creates a pending async state
- asyncFulfilled - creates a fulfilled async state
- asyncError - creates a rejected async state
- createPromise(cb) - wraps a Promise executor and always resolves to an async value
- cb function signature promise like (resolve, reject) => void
- type IAsync<V,E> - represents an async value in the store.
- V - value type
- E - error type
- result type {status: 'initial' | 'pending' | 'fulfilled' | 'rejected', value: T | null, error: E|null}
- type IAsyncValue<T> - infers the value type from IAsync.
- type IAsyncError<T> - infers the error type from IAsync.
- type IStore - Store API provided by observable-store-light.
import { createSlice, createContext, createProvider } from 'react-store-light';
type Slice = { count: number };
const Context = createContext();
const { createStore, useState } = createSlice<Slice>(Context);
const Provider = createProvider(Context)
const store = createStore({ count: 1 });Add Provider to React tree and Componentwith selector
const Counter = () => {
const [count, setCount] = store.useState('count');
return <button onClick={() => setCount((prev) => prev + 1)}>Count: {count}</button>;
};
const ProviderComponent = () => {
return (
<Provider value={[store]}>
<Counter />
</Provider>
);
};const currentCount = store.get('count');
store.set('count', currentCount + 1);Listeners are useful for reacting to state changes without triggering renders (e.g. syncing to
localStorage, logging, analytics).
store.addListener('count', (key, value) => {
console.log(`${key} changed to`, value);
});
store.removeListener('count', listener);const authStore = createStore({
isAuthenticated: false,
});
const settingsStore = createStore({
theme: 'dark',
});Each store is completely independent and has its own state and subscriptions.
MIT
Denis Kurochkin