Simple, scalable state management through functional reactive programming with observables, computed values, and reactions.
npx @tessl/cli install tessl/npm-mobx@6.13.0MobX is a battle-tested library that makes state management simple and scalable by transparently applying functional reactive programming principles. It provides a declarative approach to state management through observables, computed values, and reactions, allowing developers to build responsive applications with minimal boilerplate code.
npm install mobximport {
observable,
makeObservable,
makeAutoObservable,
computed,
action,
autorun,
reaction,
flow,
onBecomeObserved,
onBecomeUnobserved
} from "mobx";For CommonJS:
const {
observable,
makeObservable,
makeAutoObservable,
computed,
action,
autorun,
reaction,
flow,
onBecomeObserved,
onBecomeUnobserved
} = require("mobx");import { makeAutoObservable, autorun } from "mobx";
// Define observable state
class TodoStore {
todos = [];
filter = "all";
constructor() {
makeAutoObservable(this);
}
addTodo(text) {
this.todos.push({ id: Date.now(), text, completed: false });
}
get completedCount() {
return this.todos.filter(todo => todo.completed).length;
}
get filteredTodos() {
switch (this.filter) {
case "active":
return this.todos.filter(todo => !todo.completed);
case "completed":
return this.todos.filter(todo => todo.completed);
default:
return this.todos;
}
}
}
// Create store instance
const store = new TodoStore();
// React to state changes
autorun(() => {
console.log(`Total: ${store.todos.length}, Completed: ${store.completedCount}`);
});
// Modify state
store.addTodo("Learn MobX");
store.todos[0].completed = true;MobX is built around several key concepts:
The reactive system follows a simple flow: Actions modify Observable State, which triggers Computed Values to recalculate, which may trigger Reactions to run side effects.
Core functionality for creating and managing observable state that automatically tracks dependencies and triggers reactions when changed.
function observable<T>(value: T): T;
function makeObservable<T extends object>(
target: T,
annotations?: AnnotationsMap<T>,
options?: MakeObservableOptions
): T;
function makeAutoObservable<T extends object>(
target: T,
overrides?: AnnotationsMap<T>,
options?: MakeObservableOptions
): T;Derived values that automatically recalculate when their observable dependencies change, with built-in caching and lazy evaluation.
function computed<T>(fn: () => T, options?: IComputedValueOptions<T>): IComputedValue<T>;
interface IComputedValue<T> {
get(): T;
set?(value: T): void;
}Functions that modify observable state, providing performance optimizations through batching and supporting asynchronous operations through generators.
function action<T extends Function>(fn: T): T;
function action<T extends Function>(name: string, fn: T): T;
function runInAction<T>(fn: () => T): T;
function flow<R, Args extends any[]>(
generator: (...args: Args) => Generator<any, R, any>
): (...args: Args) => Promise<R>;Side effects that automatically run when observable state changes, providing different patterns for responding to state changes.
function autorun(
fn: () => void,
options?: IAutorunOptions
): IReactionDisposer;
function reaction<T>(
expression: () => T,
effect: (value: T, previousValue: T) => void,
options?: IReactionOptions<T>
): IReactionDisposer;
function when(
predicate: () => boolean,
effect?: () => void,
options?: IWhenOptions
): IReactionDisposer | Promise<void>;Helper functions for working with observable state, converting to plain values, and checking observable types.
function toJS<T>(value: T): T;
function isObservable(value: any): boolean;
function isComputed(value: any): boolean;
function isAction(fn: any): boolean;
function keys(obj: any): string[];
function values<T>(obj: T): any[];
function entries<T>(obj: T): [string, any][];
function untracked<T>(fn: () => T): T;
function onBecomeObserved(observable: any, listener: () => void): () => void;
function onBecomeUnobserved(observable: any, listener: () => void): () => void;
function defineProperty(obj: object, key: PropertyKey, descriptor: PropertyDescriptor): boolean;
function ownKeys(obj: object): PropertyKey[];Global configuration options and debugging utilities for controlling MobX behavior and troubleshooting reactive dependencies.
function configure(options: {
enforceActions?: "never" | "always" | "observed";
computedRequiresReaction?: boolean;
reactionRequiresObservable?: boolean;
observableRequiresReaction?: boolean;
isolateGlobalState?: boolean;
disableErrorBoundaries?: boolean;
safeDescriptors?: boolean;
reactionScheduler?: (f: () => void) => void;
useProxies?: "always" | "never" | "ifavailable";
}): void;
function trace(): void;
function spy(listener: (event: any) => void): () => void;interface IObservable {
[$mobx]: any;
}
interface IComputedValueOptions<T> {
name?: string;
equals?: IEqualsComparer<T>;
requiresReaction?: boolean;
keepAlive?: boolean;
}
interface IAutorunOptions {
delay?: number;
name?: string;
requiresObservable?: boolean;
scheduler?: (callback: () => void) => any;
onError?: (error: any) => void;
}
interface IReactionOptions<T> {
delay?: number;
name?: string;
equals?: IEqualsComparer<T>;
requiresObservable?: boolean;
scheduler?: (callback: () => void) => any;
onError?: (error: any) => void;
}
interface IReactionDisposer {
(): void;
[$mobx]: Reaction;
}
interface IReactionPublic {
dispose(): void;
trace(enterBreakPoint?: boolean): void;
}
interface GenericAbortSignal {
readonly aborted: boolean;
onabort?: ((...args: any) => any) | null;
addEventListener?: (...args: any) => any;
removeEventListener?: (...args: any) => any;
}
type IEqualsComparer<T> = (a: T, b: T) => boolean;
interface AnnotationsMap<T> {
[key: string]: Annotation;
}
type MakeObservableOptions = {
name?: string;
autoBind?: boolean;
};