> valtio
Manage React state with Valtio — proxy-based state that just works. Use when someone asks to "simple React state management", "Valtio", "proxy state", "mutable state in React", "alternative to Zustand/Redux", or "state management without boilerplate". Covers proxy state, subscriptions, computed values, and devtools.
curl "https://skillshub.wtf/TerminalSkills/skills/valtio?format=md"Valtio
Overview
Valtio makes React state management feel like plain JavaScript — mutate objects directly and React re-renders automatically. No reducers, no actions, no selectors. Wrap an object in proxy(), mutate it anywhere, and components that read the changed properties re-render. Based on JavaScript Proxy, it tracks which properties each component uses and only re-renders when those specific properties change.
When to Use
- Want the simplest possible state management
- Tired of Redux boilerplate or Zustand's
set()function - Sharing state between components without prop drilling
- State that's accessed/modified outside React (event handlers, WebSocket callbacks)
- Team prefers mutable patterns over immutable
Instructions
Setup
npm install valtio
Basic Store
// store/app.ts — Define state as a plain object
import { proxy, useSnapshot } from "valtio";
export const appState = proxy({
user: null as { name: string; email: string } | null,
theme: "light" as "light" | "dark",
notifications: [] as Array<{ id: string; text: string; read: boolean }>,
sidebar: { open: true, width: 280 },
});
// Mutate directly — React components auto-update
export function login(user: { name: string; email: string }) {
appState.user = user;
}
export function toggleTheme() {
appState.theme = appState.theme === "light" ? "dark" : "light";
}
export function addNotification(text: string) {
appState.notifications.push({ id: crypto.randomUUID(), text, read: false });
}
export function markAllRead() {
appState.notifications.forEach((n) => { n.read = true; });
}
export function toggleSidebar() {
appState.sidebar.open = !appState.sidebar.open;
}
Use in Components
// components/Header.tsx — Read state with useSnapshot
import { useSnapshot } from "valtio";
import { appState, toggleTheme, toggleSidebar } from "@/store/app";
export function Header() {
// useSnapshot creates a read-only snapshot
// Component ONLY re-renders when `user` or `theme` changes
// Changes to `notifications` or `sidebar` don't trigger re-render here
const snap = useSnapshot(appState);
return (
<header className="flex items-center justify-between p-4">
<button onClick={toggleSidebar}>☰</button>
<span>{snap.user?.name ?? "Guest"}</span>
<button onClick={toggleTheme}>
{snap.theme === "light" ? "🌙" : "☀️"}
</button>
</header>
);
}
// components/NotificationBell.tsx — Derived/computed values
import { useSnapshot } from "valtio";
import { appState, markAllRead } from "@/store/app";
export function NotificationBell() {
const snap = useSnapshot(appState);
const unread = snap.notifications.filter((n) => !n.read).length;
return (
<button onClick={markAllRead} className="relative">
🔔
{unread > 0 && (
<span className="absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center">
{unread}
</span>
)}
</button>
);
}
Computed Values with derive
// store/derived.ts — Computed values that auto-update
import { derive } from "valtio/utils";
import { appState } from "./app";
export const derived = derive({
unreadCount: (get) => get(appState).notifications.filter((n) => !n.read).length,
isDarkMode: (get) => get(appState).theme === "dark",
isLoggedIn: (get) => get(appState).user !== null,
});
Subscribe Outside React
// Listen to state changes outside components
import { subscribe } from "valtio";
import { appState } from "./store/app";
// Log every state change
subscribe(appState, () => {
console.log("State changed:", JSON.stringify(appState));
});
// Subscribe to specific property
subscribe(appState.sidebar, () => {
localStorage.setItem("sidebar-open", String(appState.sidebar.open));
});
// Use in WebSocket handler
socket.on("notification", (data) => {
appState.notifications.push(data); // Components auto-update
});
Examples
Example 1: Build a shopping cart
User prompt: "Build a shopping cart with add/remove/update quantity using simple state management."
The agent will create a Valtio proxy for cart state, actions that directly mutate the array, and components that reactively display cart contents and total.
Example 2: Theme and layout preferences
User prompt: "Store user preferences (theme, language, sidebar state) that persist across page loads."
The agent will create a Valtio store with localStorage sync via subscribe, and components that read preferences reactively.
Guidelines
proxy()for state,useSnapshot()for reading — always use snapshot in components- Mutate directly —
state.count++works; nosetStateorset()needed - Automatic render optimization — only re-renders when accessed properties change
subscribe()for side effects — persist to localStorage, log, syncderive()for computed values — auto-recalculates when dependencies change- Works outside React — mutate from event handlers, WebSocket, timers
- Snapshot is read-only — don't mutate
snap, mutate the originalproxy - Arrays work naturally —
push,splice,filterall trigger re-renders - Nested objects tracked —
state.user.name = "new"triggers re-render - Devtools —
import { devtools } from "valtio/utils"for Redux DevTools integration
> related_skills --same-repo
> zustand
You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.
> zoho
Integrate and automate Zoho products. Use when a user asks to work with Zoho CRM, Zoho Books, Zoho Desk, Zoho Projects, Zoho Mail, or Zoho Creator, build custom integrations via Zoho APIs, automate workflows with Deluge scripting, sync data between Zoho apps and external systems, manage leads and deals, automate invoicing, build custom Zoho Creator apps, set up webhooks, or manage Zoho organization settings. Covers Zoho CRM, Books, Desk, Projects, Creator, and cross-product integrations.
> zod
You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.
> zipkin
Deploy and configure Zipkin for distributed tracing and request flow visualization. Use when a user needs to set up trace collection, instrument Java/Spring or other services with Zipkin, analyze service dependencies, or configure storage backends for trace data.