How to Split and Compose States
Valtio's proxy-based nature makes it incredibly flexible for organizing state. You can easily split a large state into smaller, manageable pieces or compose multiple smaller states into a larger one.
Splitting a Large State
When you create a state with nested objects, each nested object is also a proxy. You can extract these nested proxies and use or subscribe to them independently.
import { proxy, useSnapshot } from 'valtio';
const state = proxy({
user: { name: 'John', email: 'john@example.com' },
settings: { theme: 'dark', notifications: true },
});
// Extract nested proxies
const userState = state.user;
const settingsState = state.settings;
// You can now use these smaller proxies directly
function UserProfile() {
// This component will only re-render when userState changes
const userSnap = useSnapshot(userState);
return <div>{userSnap.name}</div>;
}
function ThemeToggle() {
// This component only re-renders when settingsState changes
const settingsSnap = useSnapshot(settingsState);
// ...
}
Any mutation to userState
will also be reflected in the main state
object, and vice versa.
Combining Multiple States
You can also do the reverse: create multiple small, independent state proxies and combine them into a single, larger state object.
import { proxy } from 'valtio';
const userState = proxy({ name: 'John', email: 'john@example.com' });
const settingsState = proxy({ theme: 'dark', notifications: true });
const state = proxy({
user: userState,
settings: settingsState,
});
This composed state
behaves identically to the one in the first example. This pattern is powerful for organizing your application's state into logical domains or modules.
Circular State Structures
While less common, Valtio can handle circular references within its state, as proxies can refer to themselves or each other.
const state = proxy({
obj: { foo: 3 },
});
// Create a circular reference
state.obj.bar = state.obj; // 🤯
// Mutations still work as expected
state.obj.bar.foo = 4;
console.log(state.obj.foo); // 4