Skip to main content
Glama
redux-toolkit.md3.53 kB
```typescript import { configureStore, createSlice, PayloadAction, createAsyncThunk, combineReducers, } from "@reduxjs/toolkit"; import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux"; // ============================================ // Types // ============================================ interface User { id: string; name: string; email: string; } interface AuthState { user: User | null; token: string | null; status: "idle" | "loading" | "succeeded" | "failed"; error: string | null; } interface CounterState { value: number; } // ============================================ // Async Thunks // ============================================ export const loginUser = createAsyncThunk( "auth/login", async (credentials: { email: string }, { rejectWithValue }) => { try { // Simulate API call await new Promise((resolve) => setTimeout(resolve, 1000)); if (credentials.email === "error@example.com") throw new Error("Login failed"); return { user: { id: "1", name: "John Doe", email: credentials.email }, token: "fake-jwt-token", }; } catch (error: any) { return rejectWithValue(error.message); } }, ); // ============================================ // Slices // ============================================ const authSlice = createSlice({ name: "auth", initialState: { user: null, token: null, status: "idle", error: null, } as AuthState, reducers: { logout: (state) => { state.user = null; state.token = null; state.status = "idle"; }, }, extraReducers: (builder) => { builder .addCase(loginUser.pending, (state) => { state.status = "loading"; state.error = null; }) .addCase(loginUser.fulfilled, (state, action) => { state.status = "succeeded"; state.user = action.payload.user; state.token = action.payload.token; }) .addCase(loginUser.rejected, (state, action) => { state.status = "failed"; state.error = action.payload as string; }); }, }); const counterSlice = createSlice({ name: "counter", initialState: { value: 0 } as CounterState, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; }, incrementByAmount: (state, action: PayloadAction<number>) => { state.value += action.payload; }, }, }); // ============================================ // Store Configuration // ============================================ const rootReducer = combineReducers({ auth: authSlice.reducer, counter: counterSlice.reducer, }); export const store = configureStore({ reducer: rootReducer, devTools: process.env.NODE_ENV !== "production", }); // ============================================ // TypeScript Helpers // ============================================ export type RootState = ReturnType<typeof store.getState>; export type AppDispatch = typeof store.dispatch; // Use these typed hooks throughout the app instead of plain `useDispatch` and `useSelector` export const useAppDispatch = () => useDispatch<AppDispatch>(); export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector; // ============================================ // Exports // ============================================ export const { logout } = authSlice.actions; export const { increment, decrement, incrementByAmount } = counterSlice.actions; ```

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/millsydotdev/Code-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server