Proxy-state management library that makes state simple for React and vanilla JavaScript applications
—
Foundation of Valtio's reactivity providing proxy creation, immutable snapshots, and change subscriptions. The core system enables automatic state tracking without explicit setters or reducers.
Creates a reactive proxy object that automatically tracks mutations and notifies subscribers of changes.
/**
* Creates a reactive proxy object that can be tracked for changes
* @param baseObject - The object to create a proxy for (defaults to empty object)
* @returns A proxied version of the input object
* @throws Error if input is not an object
*/
function proxy<T extends object>(baseObject?: T): T;Usage Examples:
import { proxy } from "valtio";
// Simple state object
const state = proxy({ count: 0, name: "Alice" });
// Mutate directly
state.count++; // triggers change notifications
state.name = "Bob";
// Nested objects are automatically proxied
const appState = proxy({
user: { id: 1, profile: { name: "Charlie" } },
settings: { theme: "dark" }
});
// All levels are reactive
appState.user.profile.name = "Dave"; // triggers notifications
appState.settings.theme = "light";
// Arrays are also proxied
const listState = proxy({ items: [1, 2, 3] });
listState.items.push(4); // reactive
listState.items[0] = 10; // reactiveCreates an immutable snapshot of the current state of a proxy object. Snapshots are safe to read in React render functions and other contexts where immutability is important.
/**
* Creates an immutable snapshot of the current state of a proxy object
* @param proxyObject - The proxy object to create a snapshot from
* @returns An immutable snapshot of the current state
*/
function snapshot<T extends object>(proxyObject: T): Snapshot<T>;Usage Examples:
import { proxy, snapshot } from "valtio";
const state = proxy({ count: 0, items: [1, 2, 3] });
// Get immutable snapshot
const snap = snapshot(state);
console.log(snap.count); // 0
console.log(snap.items); // [1, 2, 3]
// Snapshot is readonly - these would cause TypeScript errors:
// snap.count = 1; // Error: readonly property
// snap.items.push(4); // Error: readonly array
// Snapshots reflect current state
state.count = 5;
const newSnap = snapshot(state);
console.log(newSnap.count); // 5Subscribes to changes in a proxy object, receiving detailed information about each mutation.
/**
* Subscribes to changes in a proxy object
* @param proxyObject - The proxy object to subscribe to
* @param callback - Function called when the proxy object changes
* @param notifyInSync - If true, notifications happen synchronously
* @returns Unsubscribe function to stop listening for changes
*/
function subscribe<T extends object>(
proxyObject: T,
callback: (unstable_ops: Op[]) => void,
notifyInSync?: boolean
): () => void;Usage Examples:
import { proxy, subscribe } from "valtio";
const state = proxy({ count: 0, user: { name: "Alice" } });
// Subscribe to all changes
const unsubscribe = subscribe(state, (unstable_ops) => {
console.log("Operations:", unstable_ops);
// unstable_ops contains details about what changed
});
// Make changes
state.count++;
// Logs: [["set", ["count"], 1, 0]]
state.user.name = "Bob";
// Logs: [["set", ["user", "name"], "Bob", "Alice"]]
// Stop listening
unsubscribe();
// Synchronous notifications
const syncUnsub = subscribe(state, (unstable_ops) => {
console.log("Immediate:", unstable_ops);
}, true);Gets the current version number of a proxy object, useful for debugging and advanced scenarios.
/**
* Gets the current version number of a proxy object
* @param proxyObject - The proxy object to get the version of
* @returns The current version number, or undefined if not a proxy
*/
function getVersion(proxyObject: unknown): number | undefined;Usage Examples:
import { proxy, getVersion } from "valtio";
const state = proxy({ count: 0 });
console.log(getVersion(state)); // 1 (initial version)
state.count++;
console.log(getVersion(state)); // 2
state.count++;
console.log(getVersion(state)); // 3
// Non-proxy objects return undefined
console.log(getVersion({})); // undefinedMarks an object to be excluded from proxying, keeping it as a reference in snapshots instead of deep copying.
/**
* Marks an object to be excluded from proxying
* Objects marked with ref will be kept as references in snapshots
* instead of being deeply copied.
* @param obj - The object to mark as a reference
* @returns The same object with a type marker
*/
function ref<T extends object>(obj: T): T & { $$valtioSnapshot: T };Usage Examples:
import { proxy, snapshot, ref } from "valtio";
// Without ref - objects are proxied and copied in snapshots
const regularState = proxy({
data: { heavy: "object with lots of data" }
});
// With ref - object is kept as reference
const refState = proxy({
data: ref({ heavy: "object with lots of data" })
});
const snap = snapshot(refState);
console.log(snap.data === refState.data); // true (same reference)
// Useful for immutable objects, class instances, or heavy data
class ApiClient {
constructor(private apiKey: string) {}
async fetch(url: string) { /* ... */ }
}
const appState = proxy({
client: ref(new ApiClient("key123")),
userData: { name: "Alice" }
});
// client won't be proxied, userData will betype Snapshot<T> = T extends { $$valtioSnapshot: infer S }
? S
: T extends SnapshotIgnore
? T
: T extends object
? { readonly [K in keyof T]: Snapshot<T[K]> }
: T;
type Op =
| [op: 'set', path: (string | symbol)[], value: unknown, prevValue: unknown]
| [op: 'delete', path: (string | symbol)[], prevValue: unknown];
type SnapshotIgnore =
| Date
| Map<any, any>
| Set<any>
| WeakMap<any, any>
| WeakSet<any>
| Error
| RegExp
| Function
| Primitive;
type Primitive = string | number | boolean | null | undefined | symbol | bigint;Install with Tessl CLI
npx tessl i tessl/npm-valtio