Core Package Overview
The @xndrjs/core package provides the foundation for framework-agnostic state management in xndr.
Installation
npm install @xndrjs/core
# or
pnpm add @xndrjs/core
# or
yarn add @xndrjs/core
Basic Concept
StatePort
The StatePort<T> interface is the fundamental abstraction for reactive state:
interface StatePort<T> {
get(): T;
set(value: T | ((prev: T) => T)): void;
subscribe?(callback: (value: T) => void): () => void;
}
All reactive primitives in @xndrjs/core implement StatePort.
Reactive Primitives
- ReactiveValue - For primitive values (string, number, boolean, null, undefined)
- ReactiveObject - For plain objects
- ReactiveArray - For arrays
- ReactiveSet - For Sets
- ReactiveMap - For Maps
Computed Values
Computed values automatically update when dependencies change:
import { ReactiveValue, createComputed } from '@xndrjs/core';
const a = new ReactiveValue(2);
const b = new ReactiveValue(3);
const sum = createComputed(a, b)
.as((x, y) => x + y)
.for(owner);
Lifecycle Management
Use DisposableResource for automatic cleanup:
import { DisposableResource, ReactiveValue, createComputed } from '@xndrjs/core';
class MyManager extends DisposableResource {
private count = new ReactiveValue(0);
private doubled = createComputed(this.count)
.as((c) => c * 2)
.for(this); // 'this' is the owner - this requires cleanup
// Cleanup happens automatically when disposed
// Note: ReactiveValue itself does NOT need cleanup
}
Key Exports
// StatePort pattern
export { StatePort } from './state-port';
export type { StatePort } from './state-port';
// Reactive primitives
export { ReactiveValue } from './reactive-value';
export { ReactiveObject } from './reactive-object';
export { ReactiveArray } from './reactive-array';
export { ReactiveSet } from './reactive-set';
export { ReactiveMap } from './reactive-map';
// Computed values
export { createComputed } from './create-computed';
export type { ComputedValue } from './computed-value';
// Lifecycle
export { DisposableResource } from './disposable-resource';
export type { Disposable } from './disposable';
export { makeDisposableObject } from './disposable';
export { SubscriptionsRegistry } from './subscriptions-registry';
// Utilities
export { batched } from './batched';
export { BatchContext } from './batch-context';
Next Steps
- Learn about StatePort
- Explore ReactiveValue
- Understand ComputedValue
- Read about Lifecycle Management