🧙 Valtio makes proxy-state simple for React and Vanilla
Valtio is a lightweight (3KB) state management library that leverages JavaScript Proxy objects to provide automatic reactivity for React and vanilla JavaScript applications. Created by Daishi Kato, it eliminates the boilerplate of traditional state management by allowing direct mutations to state objects without requiring actions, reducers, or dispatch functions. The library's core API consists of proxy() to create reactive state and useSnapshot() to subscribe components to fine-grained updates.
With over 1 million weekly downloads, Valtio has gained traction among developers seeking a simpler alternative to Redux-style architectures. The library's proxy-based approach automatically tracks which properties components access, triggering re-renders only when those specific properties change. This fine-grained reactivity happens without manual optimization, making it particularly appealing for teams that want to avoid reducer complexity while maintaining predictable state updates.
Valtio supports TypeScript out of the box and works seamlessly with React 16.8+, Next.js, and React Native. The library includes advanced features like derive() for computed properties with automatic memoization, subscribe() for side effects like persistence, and vanilla JavaScript support for non-React use cases. Its minimal API surface and intuitive mutation syntax make it accessible to developers transitioning from component-level state or looking to simplify existing state architectures.
The library's design philosophy centers on developer ergonomics: write state mutations as normal JavaScript assignments while the proxy handles reactivity automatically. This approach reduces cognitive overhead compared to immutable update patterns, though it requires understanding the distinction between proxies (for mutations) and snapshots (for rendering) to avoid common pitfalls in React components.
import { proxy, useSnapshot, subscribe, derive } from 'valtio';
import { useEffect } from 'react';
// Create proxy state with nested objects
const store = proxy({
todos: [],
filter: 'all',
user: { name: 'Guest', preferences: { theme: 'dark' } }
});
// Computed property using derive - automatically recalculates
const derived = derive({
filteredTodos: (get) => {
const { todos, filter } = get(store);
if (filter === 'completed') return todos.filter(t => t.completed);
if (filter === 'active') return todos.filter(t => !t.completed);
return todos;
},
completedCount: (get) => get(store).todos.filter(t => t.completed).length
});
// Persist to localStorage on changes
subscribe(store, () => {
localStorage.setItem('todos', JSON.stringify(store.todos));
});
// Actions are just functions that mutate the proxy
const actions = {
addTodo: (text) => {
store.todos.push({ id: Date.now(), text, completed: false });
},
toggleTodo: (id) => {
const todo = store.todos.find(t => t.id === id);
if (todo) todo.completed = !todo.completed;
},
setFilter: (filter) => {
store.filter = filter;
}
};
// Component using snapshot for reactivity
function TodoList() {
const snap = useSnapshot(store);
const derivedSnap = useSnapshot(derived);
useEffect(() => {
const saved = localStorage.getItem('todos');
if (saved) store.todos = JSON.parse(saved);
}, []);
return (
<div>
<h1>Welcome, {snap.user.name}</h1>
<input
type="text"
onKeyDown={(e) => {
if (e.key === 'Enter' && e.target.value) {
actions.addTodo(e.target.value);
e.target.value = '';
}
}}
/>
<div>
{['all', 'active', 'completed'].map(f => (
<button key={f} onClick={() => actions.setFilter(f)}>
{f} {f === snap.filter && '✓'}
</button>
))}
</div>
<p>Completed: {derivedSnap.completedCount}</p>
<ul>
{derivedSnap.filteredTodos.map(todo => (
<li
key={todo.id}
onClick={() => actions.toggleTodo(todo.id)}
style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
>
{todo.text}
</li>
))}
</ul>
</div>
);
}Global application state: Managing user authentication, theme settings, and feature flags across an application without prop drilling. Valtio's subscribe() API makes it trivial to sync state changes to localStorage or sessionStorage, while the lightweight proxy overhead keeps bundle sizes small for applications that don't need Redux's time-travel debugging.
Real-time collaborative features: Building dashboards or document editors where multiple data points update independently. Valtio's fine-grained reactivity ensures that updating one chart's data doesn't trigger re-renders in unrelated components, improving performance in data-heavy interfaces without manual memoization.
Form state management: Handling complex multi-step forms with conditional fields and validation. Direct mutations like formState.email = value feel natural compared to reducer dispatch patterns, and the derive() API can compute validation errors or field visibility based on current form values with automatic recalculation.
Modular feature state: Organizing state by feature domain in large applications where different teams own different modules. Each team can export their own proxy state without coordinating with a central store configuration, enabling parallel development while maintaining type safety through TypeScript.
Vanilla JavaScript state: Managing state in non-React contexts like Web Workers, service workers, or browser extensions. Valtio's subscribe() function provides reactive updates without React dependencies, making it useful for shared state logic that needs to work across different execution contexts.
👻 Primitive and flexible state management for React
Simple, scalable state management.
Recoil - A state management library for React
Predictable state container for JavaScript apps
🐻 Bear necessities for state management in React
npm install valtiopnpm add valtiobun add valtio