Redux Toolkit Setup, Store Typing, and Async Actions - Textnotes

Redux Toolkit Setup, Store Typing, and Async Actions


Learn how to manage application state in React with TypeScript using Redux Toolkit. This module explains Redux Toolkit setup, store typing, and typing asynchronous actions for type-safe state management.

1. Redux Toolkit Setup

Redux Toolkit simplifies Redux setup and includes built-in support for TypeScript.

Installation


npm install @reduxjs/toolkit react-redux
npm install --save-dev @types/react-redux

Creating a Slice


import { createSlice, PayloadAction } from "@reduxjs/toolkit";

interface CounterState {
value: number;
}

const initialState: CounterState = { value: 0 };

const counterSlice = createSlice({
name: "counter",
initialState,
reducers: {
increment(state) {
state.value += 1;
},
decrement(state) {
state.value -= 1;
},
incrementByAmount(state, action: PayloadAction<number>) {
state.value += action.payload;
}
}
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;

Redux Toolkit automatically infers types for reducers and actions.

2. Store Typing

TypeScript ensures type safety for the Redux store and dispatch.

Creating the Store


import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";

export const store = configureStore({
reducer: {
counter: counterReducer
}
});

// Infer RootState and AppDispatch
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

Using in Components


import { useSelector, useDispatch } from "react-redux";
import type { RootState, AppDispatch } from "./store";

const CounterComponent = () => {
const count = useSelector((state: RootState) => state.counter.value);
const dispatch: AppDispatch = useDispatch();

return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch(increment())}>Increment</button>
</div>
);
};

Typing the store ensures safe state access and dispatch in components.

3. Async Action Typing

Redux Toolkit provides createAsyncThunk for asynchronous actions with built-in TypeScript support.

Example


import { createAsyncThunk } from "@reduxjs/toolkit";

interface User {
id: number;
name: string;
}

export const fetchUser = createAsyncThunk<User, number>(
"users/fetchById",
async (userId: number) => {
const response = await fetch(`https://api.example.com/users/${userId}`);
return (await response.json()) as User;
}
);

Handling Async Actions in Slice


const userSlice = createSlice({
name: "user",
initialState: { user: null as User | null, status: "idle" },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => { state.status = "loading"; })
.addCase(fetchUser.fulfilled, (state, action: PayloadAction<User>) => {
state.status = "succeeded";
state.user = action.payload;
})
.addCase(fetchUser.rejected, (state) => { state.status = "failed"; });
}
});

Typing async actions ensures correct return types and payload types, reducing runtime errors in asynchronous state management.

Conclusion

Using Redux Toolkit with TypeScript provides a type-safe and scalable approach to state management in React applications. Proper store typing, typed slices, and asynchronous action typing enhance maintainability and prevent common runtime errors.