API: Utilities
SoulState provides utility functions for selector composition, scheduling, batching, and equality checks.
Import Paths
| Utility | Import |
|---|---|
batch, objectIs, createSlice, combineSlices | import { ... } from 'soulstate' |
shallow, batch, objectIs, createSlice, combineSlices | import { ... } from 'soulstate/utils' |
createSelector, selector, derived | import { ... } from 'soulstate' |
scheduleTask, flushSync | import { ... } from 'soulstate' |
Import Path
shallow is only available from 'soulstate/utils'. It is not exported from the main 'soulstate' entry.
shallow
Performs a shallow comparison of two objects, checking if their top-level properties are equal using Object.is.
Signature
function shallow<T, U>(a: T, b: U): boolean;
Parameters
a: T— The first value to compare.b: U— The second value to compare.
Return Value
boolean — true if all top-level properties are equal, false otherwise.
When to Use
Use shallow as an equalityFn when your selector returns a new object literal on each render but with the same values:
import { useStore } from 'soulstate/react';
import { shallow } from 'soulstate/utils';
function UserProfile() {
const { name, email } = useStore(
userStore,
(state) => ({ name: state.name, email: email: state.email }),
shallow
);
return <div>{name} — {email}</div>;
}
When NOT to Use
- For primitive values — use the default
Object.isinstead. - For deeply nested comparisons —
shallowonly checks top-level properties.
objectIs
The default equality function used by SoulState. Equivalent to Object.is.
Signature
const objectIs: (a: any, b: any) => boolean;
Behavior
import { objectIs } from 'soulstate';
objectIs(1, 1); // true
objectIs(NaN, NaN); // true
objectIs(0, -0); // false
objectIs({}, {}); // false
batch
Groups multiple operations into a single callback. SoulState automatically batches all setState calls via microtasks, so this utility is primarily for semantic grouping.
Signature
function batch(callback: () => void): void;
Usage
import { batch } from 'soulstate';
batch(() => {
store.setState({ count: 1 });
store.setState({ user: 'John' });
});
createSelector
Creates a memoized selector that caches its result until the input slice changes.
Signature
function createSelector<T, S, R>(
selector: (state: T) => S,
combiner: (val: S) => R,
equalityFn?: (a: S, b: S) => boolean
): (state: T) => R;
Parameters
selector— Extracts a slice from the state.combiner— Transforms the slice into a derived value.equalityFn— Optional comparison function (defaults toObject.is).
Return Value
A new selector function that memoizes its result.
Usage
import { createSelector } from 'soulstate';
const selectDoubled = createSelector(
(s: { count: number }) => s.count,
(count) => count * 2
);
// First call: computes
selectDoubled(store.getState()); // 2
// Second call with same input: returns cached result
selectDoubled(store.getState()); // 2 (no recomputation)
selector
Identity function for type inference. Returns the function unchanged.
Signature
function selector<T, S>(fn: (state: T) => S): (state: T) => S;
Usage
import { selector } from 'soulstate';
const selectCount = selector((s: { count: number }) => s.count);
selectCount({ count: 42 }); // 42
derived
Composable selector utility. Combines multiple selectors or computed values into a single derived selector.
Signature
function derived<T, S extends any[], R>(
...args: [
...{ [K in keyof S]: ((state: T) => S[K]) | { value: S[K] } },
(...vals: S) => R
]
): (state: T) => R;
Parameters
...selectors— An array of selector functions orComputedobjects, followed by a combiner function as the last argument.
Return Value
A new selector function that computes the derived value.
Usage
import { derived } from 'soulstate';
const selectFullName = derived(
(s: { first: string; last: string }) => s.first,
(s: { first: string; last: string }) => s.last,
(first, last) => `${first} ${last}`
);
selectFullName({ first: 'Jane', last: 'Doe' }); // "Jane Doe"
Composing with Computed
import { createStore, derived } from 'soulstate';
const store = createStore({ a: 1, b: 2 });
const aComp = store.computed(s => s.a);
const bComp = store.computed(s => s.b);
const sum = derived(aComp, bComp, (a, b) => a + b);
sum(store.getState()); // 3
scheduleTask
Schedules a task on the microtask queue. Duplicate tasks (same function reference) are deduplicated.
Signature
function scheduleTask(task: () => void): void;
Behavior
- Tasks are executed in FIFO order during the next microtask flush.
- If the same function reference is already queued, it is not added again.
- Tasks scheduled during a flush are executed in a subsequent microtask.
Internal Use
scheduleTask is used internally by SoulState's runtime to batch state updates. You rarely need to call it directly.
flushSync
Executes a callback immediately. Unlike scheduleTask, this does NOT drain the microtask notification queue.
Signature
function flushSync<T>(callback: () => T): T;
Usage
import { flushSync } from 'soulstate';
flushSync(() => {
// Executes synchronously
console.log('runs immediately');
});
Caution
flushSync executes the callback immediately but does not process pending microtask notifications. Subscriber notifications from prior setState calls may still be pending.
createSlice
Creates a domain-specific state slice with auto-injected actions. See Slices API for full documentation.
combineSlices
Merges multiple slice creators into a single state creator. See Slices API for full documentation.
Performance Characteristics
shallow: O(n) where n is the number of top-level properties.objectIs: O(1) — delegates toObject.is.createSelector: O(1) memoized after first call; recomputes only when input slice changes.batch: No overhead — directly invokes the callback.scheduleTask: O(1) enqueue; deduplicates by reference equality.flushSync: O(1) — synchronous callback invocation.