Command Palette
Search for a command to run...
For complex related state, I recommend using useReducer instead of multiple useState calls. Here's why:
typescriptinterface DashboardState { conversations: Conversation[]; selectedId: string | null; isLoading: boolean; error: string | null; } type Action = | { type: 'FETCH_START' } | { type: 'FETCH_SUCCESS'; payload: Conversation[] } | { type: 'SELECT'; payload: string }; function dashboardReducer(state: DashboardState, action: Action): DashboardState { switch (action.type) { case 'FETCH_START': return { ...state, isLoading: true, error: null }; case 'FETCH_SUCCESS': return { ...state, conversations: action.payload, isLoading: false }; case 'SELECT': return { ...state, selectedId: action.payload }; } }
For even more complex scenarios (global state shared across components), consider Zustand — it's lightweight and works great with React Server Components.
Here's a clean pattern combining useReducer + Context:
typescriptconst DashboardContext = createContext<{ state: DashboardState; dispatch: React.Dispatch<Action>; } | null>(null); export function DashboardProvider({ children }: { children: React.ReactNode }) { const [state, dispatch] = useReducer(dashboardReducer, initialState); return ( <DashboardContext.Provider value={{ state, dispatch }}> {children} </DashboardContext.Provider> ); } export function useDashboard() { const context = useContext(DashboardContext); if (!context) throw new Error('useDashboard must be used within DashboardProvider'); return context; }
However, for production apps I'd recommend Zustand over Context + useReducer because: