State Management
How state is managed in Viben frontend applications.
Overview
Viben Desktop uses Zustand for global state management and React Query for server state. The architecture follows a clear separation between local component state, global UI state, and server-synchronized state.
State Categories
Local State
Used for component-specific UI state that doesn't need to be shared:
const [isOpen, setIsOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
Global State (Zustand)
Used for application-wide UI state that needs to persist across route changes:
// stores/workspace-store.ts
interface WorkspaceStore {
activeWorkspaceId: string | null;
setActiveWorkspace: (id: string) => void;
}
Server State (React Query / Gateway Client)
Used for data fetched from the Gateway API:
// Fetched via GatewayClient and managed by hooks
const { agents, loading, refresh } = useAgents({ workspacePath });
const { items, groupChats, executors } = useChatList({ workspacePath });
URL State
Used for navigation and deep-linking:
// Route parameters drive which workspace/agent/session is active
const { workspaceId, agentId, sessionId } = useParams();
When to Use Global State
Promote state to global (Zustand store) when:
- Multiple components need to read/write the same data
- Route changes should not reset the state
- Background processes need to update state that components observe
- User preferences that persist across sessions
Do NOT use global state for:
- Data that only one component uses
- Server data (use React Query/hooks instead)
- Form state (keep in component or form library)
Server State
Server data is cached and synchronized through the Gateway client hooks:
// Example: useAgents hook
export function useAgents(options: UseAgentsOptions): UseAgentsReturn {
// Fetches from GET /api/agent
// Provides CRUD operations via POST/PATCH/DELETE
// Auto-refreshes on mutations
}
Key patterns:
- Data is fetched on component mount
- Mutations trigger automatic refetch
- Loading and error states are exposed
- Stale data is shown while refetching
Common Mistakes
- Storing server data in Zustand - Use hooks that fetch from Gateway instead
- Over-globalizing state - Keep state local unless it truly needs to be shared
- Not cleaning up subscriptions - Always return cleanup functions from useEffect
- Mutating state directly - Always use Zustand's
setfunction or React's state setters