ilokesto

2.0 migration

This guide covers the state construction and notification changes introduced in 2.0.

Create once, bind explicitly

Before:

import { create } from '@ilokesto/state/react';
const useCounter = create({ count: 0 });

Recommended:

import { createStore } from '@ilokesto/state';
import { bind } from '@ilokesto/state/react';
const counter = createStore({ count: 0 });
const useCounter = bind(counter);

The original convenience API remains available. Use createReducer(reducer, valueOrStore) and bindReducer(handle) when actions, rather than values, drive updates. The previously empty root entrypoint now exports vanilla construction and composition.

Notification behavior changes

Before 2.02.0
Nested updates recursively interrupt deliveryCommits are immediate; notifications drain synchronously in FIFO order
Later selectors can miss intermediate commitsSelectors evaluate each captured commit
A removed listener can still run in the current passUnsubscribe immediately skips pending delivery
Duplicate plain callbacks share one registrationEvery registration owns a separate disposer
A listener error prevents later listeners from runningDelivery continues and reports an AggregateError afterward

Use the callback arguments of subscribeSelector to observe each transition. Plain subscribe is an invalidation signal with no arguments: getState() inside it reads the latest committed value, which can be newer than the current delivery record. New subscriptions do not receive records captured before registration.

Handle listener failures around the outermost synchronous update. Inspect AggregateError.errors for the original thrown values. State is already committed; an error is not a rollback signal. Updater and middleware errors still propagate directly rather than being converted to notification errors.

Functions and lifecycle

Use store.set(fn) to store a function as a value. store.update(updater) is explicit computation. setState(fn) retains its updater meaning. Svelte set(fn) now correctly stores the function without invoking it.

Store prototype methods still require their receiver. Subclasses and middleware capability properties are retained. Use ReadableStore<T> for readers and StoreApi<T> for writable structural integrations.

No framework support or middleware feature has been removed. Existing pipe ordering, reducer identity, SSR initial snapshots, and resource cleanup contracts remain in place. Applications depending on the old notification edge cases must update when moving to 2.0.

On this page