Documentation Index Fetch the complete documentation index at: https://mintlify.com/LegendApp/legend-state/llms.txt
Use this file to discover all available pages before exploring further.
Get up and running with Legend-State in just a few minutes. This guide will walk you through installation, basic usage, and your first reactive component.
Installation
Install Legend-State using your preferred package manager:
npm install @legendapp/state
Basic usage
Create an observable
Create observables to hold your state. Observables can contain any value - primitives, objects, arrays, or even functions. import { observable } from '@legendapp/state' ;
// Primitive observable
const count$ = observable ( 0 );
// Object observable
const user$ = observable ({
name: 'Alice' ,
age: 30
});
// Array observable
const todos$ = observable ([
{ id: 1 , text: 'Learn Legend-State' , completed: false },
{ id: 2 , text: 'Build something awesome' , completed: false }
]);
Get and set values
Use get() to read values and set() to update them. It’s that simple! // Get values
console . log ( count$ . get ()); // 0
console . log ( user$ . name . get ()); // 'Alice'
// Set values
count$ . set ( 1 );
user$ . name . set ( 'Bob' );
// Update with a function
count$ . set ( prev => prev + 1 );
// Update nested objects
user$ . set ({ name: 'Charlie' , age: 25 });
Observe changes
React to changes with the observe() function. It runs immediately and whenever tracked observables change. import { observe } from '@legendapp/state' ;
// Observe runs whenever count$ changes
observe (() => {
console . log ( 'Count changed:' , count$ . get ());
});
// Will log: "Count changed: 2"
count$ . set ( 2 );
Create computed observables
Computed observables automatically update when their dependencies change. // Computed observable using a function
const doubled$ = observable (() => count$ . get () * 2 );
console . log ( doubled$ . get ()); // 4 (count is 2)
count$ . set ( 5 );
console . log ( doubled$ . get ()); // 10
React integration
Legend-State provides powerful React integration with hooks and components for building reactive UIs.
Use the observer HOC
The observer HOC makes components automatically re-render when observables they access change. import { observable } from '@legendapp/state' ;
import { observer } from '@legendapp/state/react' ;
const state$ = observable ({
count: 0
});
const Counter = observer ( function Counter () {
// Component automatically tracks access to count
const count = state$ . count . get ();
return (
< div >
< p > Count: { count } </ p >
< button onClick = { () => state$ . count . set ( c => c + 1 ) } >
Increment
</ button >
</ div >
);
});
Use the useObservable hook
Create local component state with useObservable(). It works just like observables but is scoped to the component. import { useObservable } from '@legendapp/state/react' ;
function TodoList () {
const todos$ = useObservable ([
{ id: 1 , text: 'Learn Legend-State' , completed: false }
]);
const addTodo = () => {
const newTodo = {
id: Date . now (),
text: 'New todo' ,
completed: false
};
todos$ . set ( prev => [ ... prev , newTodo ]);
};
return (
< div >
{ todos$ . get (). map ( todo => (
< div key = { todo . id } > { todo . text } </ div >
)) }
< button onClick = { addTodo } > Add Todo </ button >
</ div >
);
}
Use fine-grained rendering
The Memo component enables fine-grained reactivity - it updates itself without re-rendering the parent component. import { observable } from '@legendapp/state' ;
import { Memo } from '@legendapp/state/react' ;
const state$ = observable ({ count: 0 });
function FineGrainedCounter () {
// This component NEVER re-renders!
return (
< div >
Count: < Memo > { state$ . count } </ Memo >
< button onClick = { () => state$ . count . set ( c => c + 1 ) } >
Increment
</ button >
</ div >
);
}
Complete example
Here’s a complete todo list example that demonstrates multiple concepts:
import { observable } from '@legendapp/state' ;
import { observer , useObservable , For , Memo } from '@legendapp/state/react' ;
const state$ = observable ({
todos: []
});
const TodoApp = observer ( function TodoApp () {
const input$ = useObservable ( '' );
const addTodo = () => {
const text = input$ . get ();
if ( ! text . trim ()) return ;
state$ . todos . set ( prev => [
... prev ,
{ id: Date . now (), text , completed: false }
]);
input$ . set ( '' );
};
const toggleTodo = ( id : number ) => {
const todo = state$ . todos . find ( t => t . id . peek () === id );
if ( todo ) {
todo . completed . set ( c => ! c );
}
};
return (
< div >
< h1 > Todo List </ h1 >
< div >
< input
value = { input$ . get () }
onChange = { e => input$ . set ( e . target . value ) }
placeholder = "Add a todo..."
/>
< button onClick = { addTodo } > Add </ button >
</ div >
< For each = { state$ . todos } >
{ todo$ => (
< div >
< input
type = "checkbox"
checked = { todo$ . completed . get () }
onChange = { () => toggleTodo ( todo$ . id . peek ()) }
/>
< span
style = { {
textDecoration: todo$ . completed . get () ? 'line-through' : 'none'
} }
>
< Memo > { todo$ . text } </ Memo >
</ span >
</ div >
) }
</ For >
</ div >
);
});
Key concepts
Observables Learn about creating and working with observables
React Hooks Explore React integration hooks like useObservable and useSelector
Fine-Grained Rendering Master fine-grained reactivity for maximum performance
Persistence & Sync Set up automatic persistence and real-time sync
Next steps
Core concepts Dive deep into observables, computed values, and reactivity
React integration Learn about all React hooks and components
Sync & persistence Add local-first sync and persistence to your app
TypeScript guide Get the most out of TypeScript with Legend-State