0
# Legend State
1
2
Legend State is a super fast and powerful state management library for JavaScript and React applications that prioritizes ease of use, performance, and minimal boilerplate. It provides a proxy-based observable system with fine-grained reactivity that enables components to re-render only when specifically accessed state changes, resulting in exceptional performance benchmarks.
3
4
## Package Information
5
6
- **Package Name**: @legendapp/state
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @legendapp/state`
10
11
## Core Imports
12
13
```typescript
14
import { observable, computed, when } from "@legendapp/state";
15
```
16
17
For React integration:
18
19
```typescript
20
import { useObservable, Reactive } from "@legendapp/state/react";
21
```
22
23
For persistence:
24
25
```typescript
26
import { persistObservable } from "@legendapp/state/persist";
27
```
28
29
CommonJS:
30
31
```javascript
32
const { observable, computed, when } = require("@legendapp/state");
33
```
34
35
## Basic Usage
36
37
```typescript
38
import { observable, computed } from "@legendapp/state";
39
import { useObservable } from "@legendapp/state/react";
40
41
// Create observables
42
const user$ = observable({
43
name: "Alice",
44
age: 30,
45
settings: {
46
theme: "dark"
47
}
48
});
49
50
// Create computed values
51
const displayName$ = computed(() => `${user$.name.get()} (${user$.age.get()})`);
52
53
// Observe changes
54
user$.onChange(() => {
55
console.log("User changed:", user$.get());
56
});
57
58
// React component
59
function UserProfile() {
60
const localUser$ = useObservable({ name: "", email: "" });
61
62
return (
63
<Reactive.div>
64
<input
65
value={localUser$.name.get()}
66
onChange={e => localUser$.name.set(e.target.value)}
67
/>
68
<p>Name: {localUser$.name.get()}</p>
69
</Reactive.div>
70
);
71
}
72
```
73
74
## Architecture
75
76
Legend State is built around several key components:
77
78
- **Observable System**: Proxy-based observables with fine-grained reactivity tracking
79
- **Computed Values**: Automatic dependency tracking and lazy evaluation
80
- **React Integration**: Optimized hooks and components for React applications
81
- **Persistence Layer**: Comprehensive offline-first data synchronization
82
- **Type Safety**: Full TypeScript integration with preserved type information
83
- **Performance**: Minimal re-renders through precise change detection
84
85
## Capabilities
86
87
### Core Observables
88
89
Core observable creation and manipulation functions for reactive state management.
90
91
```typescript { .api }
92
function observable<T>(value?: T): Observable<T>;
93
function observablePrimitive<T>(value?: T): ObservablePrimitive<T>;
94
function computed<T>(compute: () => T): ObservableComputed<T>;
95
function event(): ObservableEvent;
96
function observe<T>(selector: Selector<T>, reaction?: (e: ObserveEvent<T>) => any): () => void;
97
function proxy<T>(target: T): T;
98
function trackSelector<T>(selector: Selector<T>): () => T;
99
```
100
101
[Core Observables](./core-observables.md)
102
103
### React Integration
104
105
React hooks and components for building reactive user interfaces with Legend State.
106
107
```typescript { .api }
108
function useObservable<T>(initialValue?: T | (() => T) | (() => Promise<T>)): Observable<T>;
109
function useObserveEffect<T>(selector: () => T, effect: (value: T) => void): void;
110
function Reactive<T extends keyof JSX.IntrinsicElements>(
111
props: ComponentProps<T>
112
): JSX.Element;
113
```
114
115
[React Integration](./react-integration.md)
116
117
### Persistence
118
119
Comprehensive persistence system for offline-first applications with local storage and remote sync capabilities.
120
121
```typescript { .api }
122
function persistObservable<T>(
123
obs: Observable<T>,
124
config: ObservablePersistenceConfig<T>
125
): void;
126
function configureObservablePersistence(
127
config: ObservablePersistenceConfig
128
): void;
129
```
130
131
[Persistence](./persistence.md)
132
133
### Helper Functions
134
135
Utility functions for working with observables, including type checking, object manipulation, and path operations.
136
137
```typescript { .api }
138
function isObservable(value: any): boolean;
139
function when<T>(predicate: Selector<T>, effect?: (value: T) => any | (() => any)): Promise<T>;
140
function whenReady<T>(predicate: Selector<T>, effect?: (value: T) => any | (() => any)): Promise<T>;
141
function batch(fn: () => void): void;
142
function beginBatch(): void;
143
function endBatch(): void;
144
function computeSelector<T>(selector: Selector<T>): T;
145
function getObservableIndex(obs: Observable<any>): ObservableChild<number>;
146
function isObservableValueReady(value: any): boolean;
147
function lockObservable<T>(obs: Observable<T>, value: T): void;
148
function mergeIntoObservable<T>(target: Observable<T>, ...sources: T[]): void;
149
function opaqueObject<T>(value: T): T;
150
function setSilently<T>(obs: Observable<T>, value: T): void;
151
function hasOwnProperty(obj: any, key: string): boolean;
152
function isArray(value: any): boolean;
153
function isBoolean(value: any): boolean;
154
function isEmpty(value: any): boolean;
155
function isFunction(value: any): boolean;
156
function isObject(value: any): boolean;
157
function isPrimitive(value: any): boolean;
158
function isPromise(value: any): boolean;
159
function isString(value: any): boolean;
160
function isSymbol(value: any): boolean;
161
```
162
163
[Helper Functions](./helper-functions.md)
164
165
### Configuration
166
167
Configuration modules for enabling various Legend State features and optimizations.
168
169
```typescript { .api }
170
function configureLegendState(config: { observableFunctions?: ObservableFunctions }): void;
171
```
172
173
[Configuration](./configuration.md)
174
175
## Types
176
177
Core type definitions used throughout the Legend State API.
178
179
```typescript { .api }
180
type TrackingType = undefined | true | symbol;
181
182
interface GetOptions {
183
shallow: boolean;
184
}
185
186
type Selector<T> = () => T;
187
188
type ObservableListenerDispose = () => void;
189
190
interface Observable<T> {
191
get(options?: TrackingType | GetOptions): T;
192
set(value: T | ((prev: T) => T) | Promise<T>): void;
193
peek(): T;
194
onChange(
195
callback: ListenerFn<T>,
196
options?: {
197
trackingType?: TrackingType;
198
initial?: boolean;
199
immediate?: boolean;
200
noArgs?: boolean;
201
}
202
): ObservableListenerDispose;
203
assign(value: T | Partial<T>): void;
204
delete(): void;
205
}
206
207
type ObservablePrimitive<T> = [T] extends [boolean]
208
? ObservablePrimitiveBaseFns<T> & ObservablePrimitiveBooleanFns<T>
209
: ObservablePrimitiveBaseFns<T>;
210
211
interface ObservablePrimitiveBaseFns<T> {
212
get(options?: TrackingType | GetOptions): T;
213
set(value: T | ((prev: T) => T) | Promise<T>): void;
214
peek(): T;
215
onChange(
216
callback: ListenerFn<T>,
217
options?: {
218
trackingType?: TrackingType;
219
initial?: boolean;
220
immediate?: boolean;
221
noArgs?: boolean;
222
}
223
): ObservableListenerDispose;
224
delete(): void;
225
}
226
227
interface ObservablePrimitiveBooleanFns<T> {
228
toggle(): T;
229
}
230
231
interface ObservableComputed<T> extends Observable<T> {
232
// Computed observables are read-only
233
}
234
235
interface ObservableEvent {
236
fire(...args: any[]): void;
237
on(callback: (...args: any[]) => void): ObservableListenerDispose;
238
}
239
240
interface ObserveEvent<T> {
241
cancel?: boolean;
242
value?: T;
243
}
244
245
interface ListenerParams<T> {
246
value: T;
247
getPrevious: () => T;
248
changes: Change[];
249
}
250
251
type ListenerFn<T> = (params: ListenerParams<T>) => void;
252
253
interface Change {
254
path: string[];
255
pathTypes: TypeAtPath[];
256
valueAtPath: any;
257
prevAtPath: any;
258
}
259
260
type TypeAtPath = 'object' | 'array' | 'map' | 'set';
261
262
interface ObservableFunctions {
263
[key: string]: any;
264
}
265
266
interface WithState {
267
state?: ObservableState;
268
_state?: ObservableState;
269
}
270
271
interface ObservableState {
272
isLoaded: boolean;
273
error?: Error;
274
}
275
276
interface ObservableComputedTwoWay<T, T2 = T> extends Observable<T> {
277
set(value: T2): void;
278
}
279
280
interface NodeValue {
281
// Internal node representation
282
}
283
284
interface ObserveOptions {
285
fromComputed?: boolean;
286
immediate?: boolean;
287
}
288
289
type ObservableChild<T> = Observable<T>;
290
```