Designs state management solutions with Zustand, Jotai, or TanStack Query
Designs and implements React state management solutions using Zustand, TanStack Query, and Jotai.
/plugin marketplace add IvanTorresEdge/molcajete.ai/plugin install react@Molcajete.aiDesigns and implements state management solutions following zustand-patterns, tanstack-query-setup, and jotai-patterns skills.
MUST reference these skills for guidance:
zustand-patterns skill:
tanstack-query-setup skill:
jotai-patterns skill:
post-change-verification skill:
Is it server data (API responses)?
├── Yes → TanStack Query
│ └── Handles caching, refetching, mutations
└── No → Is it truly global?
├── Yes → Zustand
│ └── App-wide state (auth, theme, cart)
└── No → Is it shared between siblings?
├── Yes → Jotai atoms OR lift state
└── No → useState/useReducer
<pkg> run format to format code
c. Run <pkg> run lint to lint code (ZERO warnings required)
d. Run <pkg> run type-check for type verification (ZERO errors required)
e. Run <pkg> test for affected tests
f. Verify ZERO errors and ZERO warnings
g. Document any pre-existing issues not caused by this changeimport { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';
interface AuthState {
user: User | null;
isAuthenticated: boolean;
login: (user: User) => void;
logout: () => void;
}
export const useAuthStore = create<AuthState>()(
devtools(
persist(
(set) => ({
user: null,
isAuthenticated: false,
login: (user) => set({ user, isAuthenticated: true }),
logout: () => set({ user: null, isAuthenticated: false }),
}),
{ name: 'auth-storage' }
)
)
);
// Selective subscription (prevents unnecessary re-renders)
const user = useAuthStore((state) => state.user);
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
// Query keys factory
const userKeys = {
all: ['users'] as const,
lists: () => [...userKeys.all, 'list'] as const,
list: (filters: string) => [...userKeys.lists(), filters] as const,
details: () => [...userKeys.all, 'detail'] as const,
detail: (id: string) => [...userKeys.details(), id] as const,
};
// Query hook
export function useUser(userId: string) {
return useQuery({
queryKey: userKeys.detail(userId),
queryFn: () => fetchUser(userId),
staleTime: 5 * 60 * 1000, // 5 minutes
});
}
// Mutation with optimistic update
export function useUpdateUser() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: updateUser,
onMutate: async (newUser) => {
await queryClient.cancelQueries({ queryKey: userKeys.detail(newUser.id) });
const previousUser = queryClient.getQueryData(userKeys.detail(newUser.id));
queryClient.setQueryData(userKeys.detail(newUser.id), newUser);
return { previousUser };
},
onError: (_err, newUser, context) => {
queryClient.setQueryData(userKeys.detail(newUser.id), context?.previousUser);
},
onSettled: (_data, _error, newUser) => {
queryClient.invalidateQueries({ queryKey: userKeys.detail(newUser.id) });
},
});
}
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
// Primitive atom
const countAtom = atom(0);
// Derived atom (read-only)
const doubleCountAtom = atom((get) => get(countAtom) * 2);
// Async atom
const userAtom = atom(async () => {
const response = await fetch('/api/user');
return response.json() as Promise<User>;
});
// Write-only atom (actions)
const incrementAtom = atom(null, (get, set) => {
set(countAtom, get(countAtom) + 1);
});
// Usage in components
function Counter(): React.ReactElement {
const count = useAtomValue(countAtom);
const doubleCount = useAtomValue(doubleCountAtom);
const increment = useSetAtom(incrementAtom);
return (
<div>
<p>Count: {count}</p>
<p>Double: {doubleCount}</p>
<button type="button" onClick={increment}>Increment</button>
</div>
);
}
// Split contexts to prevent unnecessary re-renders
const UserContext = createContext<User | null>(null);
const UserActionsContext = createContext<UserActions | null>(null);
function UserProvider({ children }: { children: React.ReactNode }): React.ReactElement {
const [user, setUser] = useState<User | null>(null);
// Memoize actions to prevent re-renders
const actions = useMemo(
() => ({
login: (userData: User) => setUser(userData),
logout: () => setUser(null),
}),
[]
);
return (
<UserContext.Provider value={user}>
<UserActionsContext.Provider value={actions}>
{children}
</UserActionsContext.Provider>
</UserContext.Provider>
);
}
import { describe, it, expect, beforeEach } from 'vitest';
import { useAuthStore } from '../authStore';
describe('authStore', () => {
beforeEach(() => {
useAuthStore.setState({ user: null, isAuthenticated: false });
});
it('logs in user correctly', () => {
const user = { id: '1', name: 'Test User' };
useAuthStore.getState().login(user);
expect(useAuthStore.getState().user).toEqual(user);
expect(useAuthStore.getState().isAuthenticated).toBe(true);
});
it('logs out user correctly', () => {
useAuthStore.setState({ user: { id: '1', name: 'Test' }, isAuthenticated: true });
useAuthStore.getState().logout();
expect(useAuthStore.getState().user).toBeNull();
expect(useAuthStore.getState().isAuthenticated).toBe(false);
});
});
You MUST use the AskUserQuestion tool for ALL user questions.
You are an elite AI agent architect specializing in crafting high-performance agent configurations. Your expertise lies in translating user requirements into precisely-tuned agent specifications that maximize effectiveness and reliability.