0
# Action Management
1
2
Action creators and binding utilities for managing action dispatch. Actions are the only way to send data to the store, and action creators provide a clean way to create and dispatch actions with automatic binding to the store's dispatch function.
3
4
## Capabilities
5
6
### Bind Action Creators
7
8
Wraps action creators with dispatch calls so they can be invoked directly without manually calling dispatch.
9
10
```typescript { .api }
11
/**
12
* Wraps a single action creator with dispatch
13
* @param actionCreator - A function that creates actions
14
* @param dispatch - The dispatch function from your Redux store
15
* @returns The action creator wrapped with dispatch call
16
*/
17
function bindActionCreators<A, C extends ActionCreator<A>>(
18
actionCreator: C,
19
dispatch: Dispatch
20
): C;
21
22
/**
23
* Wraps multiple action creators with dispatch
24
* @param actionCreators - Object whose values are action creator functions
25
* @param dispatch - The dispatch function from your Redux store
26
* @returns Object with same keys, but action creators wrapped with dispatch
27
*/
28
function bindActionCreators<A, M extends ActionCreatorsMapObject<A>>(
29
actionCreators: M,
30
dispatch: Dispatch
31
): M;
32
33
/**
34
* Wraps a single action creator with flexible typing
35
* @param actionCreator - A function that creates actions
36
* @param dispatch - The dispatch function from your Redux store
37
* @returns The action creator wrapped with dispatch call
38
*/
39
function bindActionCreators<A extends ActionCreator<any>, B extends ActionCreator<any>>(
40
actionCreator: A,
41
dispatch: Dispatch
42
): B;
43
44
function bindActionCreators<M extends ActionCreatorsMapObject, N extends ActionCreatorsMapObject>(
45
actionCreators: M,
46
dispatch: Dispatch
47
): N;
48
```
49
50
**Usage Examples:**
51
52
```typescript
53
import { bindActionCreators } from "redux";
54
55
// Action creators
56
const increment = () => ({ type: "INCREMENT" });
57
const decrement = () => ({ type: "DECREMENT" });
58
const addTodo = (text: string) => ({ type: "ADD_TODO", payload: { text } });
59
60
// Bind single action creator
61
const boundIncrement = bindActionCreators(increment, store.dispatch);
62
boundIncrement(); // Automatically dispatches the action
63
64
// Bind multiple action creators
65
const actionCreators = { increment, decrement, addTodo };
66
const boundActionCreators = bindActionCreators(actionCreators, store.dispatch);
67
68
// Use bound action creators directly
69
boundActionCreators.increment(); // Dispatches increment action
70
boundActionCreators.addTodo("Learn Redux"); // Dispatches add todo action
71
72
// Common pattern in React components
73
const mapDispatchToProps = (dispatch) => bindActionCreators({
74
increment,
75
decrement,
76
addTodo
77
}, dispatch);
78
```
79
80
### Action Creator Interface
81
82
The interface that action creator functions must implement.
83
84
```typescript { .api }
85
/**
86
* An action creator is a function that creates an action
87
* @template A - The type of action returned
88
* @template P - The parameter types accepted by the action creator
89
*/
90
interface ActionCreator<A, P extends any[] = any[]> {
91
(...args: P): A;
92
}
93
94
/**
95
* Object whose values are action creator functions
96
* @template A - The type of actions created
97
* @template P - The parameter types accepted by action creators
98
*/
99
interface ActionCreatorsMapObject<A = any, P extends any[] = any[]> {
100
[key: string]: ActionCreator<A, P>;
101
}
102
```
103
104
**Usage Examples:**
105
106
```typescript
107
// Simple action creators
108
const reset: ActionCreator<{ type: "RESET" }> = () => ({ type: "RESET" });
109
110
const setCount: ActionCreator<{ type: "SET_COUNT"; payload: number }, [number]> = (
111
count: number
112
) => ({ type: "SET_COUNT", payload: count });
113
114
// Action creators with multiple parameters
115
const updateUser: ActionCreator<
116
{ type: "UPDATE_USER"; payload: { id: string; name: string } },
117
[string, string]
118
> = (id: string, name: string) => ({
119
type: "UPDATE_USER",
120
payload: { id, name }
121
});
122
123
// Action creator map
124
const userActionCreators: ActionCreatorsMapObject = {
125
login: (username: string, password: string) => ({
126
type: "LOGIN",
127
payload: { username, password }
128
}),
129
logout: () => ({ type: "LOGOUT" }),
130
updateProfile: (profile: object) => ({
131
type: "UPDATE_PROFILE",
132
payload: profile
133
})
134
};
135
```
136
137
## Action Types
138
139
### Base Action Types
140
141
The fundamental action types that all Redux actions must extend.
142
143
```typescript { .api }
144
/**
145
* An action is a plain object that represents an intention to change the state
146
* @template T - The type of the action's type tag
147
*/
148
type Action<T extends string = string> = {
149
type: T;
150
};
151
152
/**
153
* An Action type which accepts any other properties
154
* This is mainly for the use of the Reducer type
155
*/
156
interface UnknownAction extends Action {
157
[extraProps: string]: unknown;
158
}
159
160
/**
161
* An Action type which accepts any other properties
162
* @deprecated Use Action or UnknownAction instead
163
*/
164
interface AnyAction extends Action {
165
[extraProps: string]: any;
166
}
167
```
168
169
**Usage Examples:**
170
171
```typescript
172
// Basic action
173
const basicAction: Action = { type: "BASIC_ACTION" };
174
175
// Action with specific type
176
const specificAction: Action<"SPECIFIC_TYPE"> = { type: "SPECIFIC_TYPE" };
177
178
// Action with payload using UnknownAction
179
const actionWithPayload: UnknownAction = {
180
type: "WITH_PAYLOAD",
181
payload: { data: "some data" },
182
meta: { timestamp: Date.now() }
183
};
184
185
// Typed action interface
186
interface CounterAction extends Action {
187
type: "INCREMENT" | "DECREMENT" | "SET_COUNT";
188
payload?: number;
189
}
190
191
const counterActions: CounterAction[] = [
192
{ type: "INCREMENT" },
193
{ type: "DECREMENT" },
194
{ type: "SET_COUNT", payload: 10 }
195
];
196
```
197
198
## Advanced Patterns
199
200
### Async Action Creators
201
202
Action creators that return functions (thunks) for async operations:
203
204
```typescript
205
// Async action creator (requires redux-thunk middleware)
206
const fetchUser = (userId: string) => {
207
return async (dispatch: Dispatch, getState: () => any) => {
208
dispatch({ type: "FETCH_USER_START" });
209
210
try {
211
const user = await api.getUser(userId);
212
dispatch({ type: "FETCH_USER_SUCCESS", payload: user });
213
} catch (error) {
214
dispatch({ type: "FETCH_USER_ERROR", payload: error.message });
215
}
216
};
217
};
218
219
// Bind async action creators
220
const boundAsyncActions = bindActionCreators({
221
fetchUser,
222
fetchPosts: (userId: string) => async (dispatch: Dispatch) => {
223
// async logic
224
}
225
}, store.dispatch);
226
```
227
228
### Action Creator Factories
229
230
Functions that create action creators:
231
232
```typescript
233
// Action creator factory
234
const createAsyncActionCreators = (entityName: string) => ({
235
request: () => ({ type: `${entityName.toUpperCase()}_REQUEST` }),
236
success: (data: any) => ({
237
type: `${entityName.toUpperCase()}_SUCCESS`,
238
payload: data
239
}),
240
failure: (error: string) => ({
241
type: `${entityName.toUpperCase()}_FAILURE`,
242
payload: error
243
})
244
});
245
246
// Create action creators for different entities
247
const userActions = createAsyncActionCreators("user");
248
const postActions = createAsyncActionCreators("post");
249
250
// Bind them to dispatch
251
const boundUserActions = bindActionCreators(userActions, store.dispatch);
252
```
253
254
### Conditional Action Binding
255
256
Selectively bind action creators based on conditions:
257
258
```typescript
259
const createBoundActions = (user: User, dispatch: Dispatch) => {
260
const baseActions = { logout, updateProfile };
261
262
if (user.role === "admin") {
263
return bindActionCreators({
264
...baseActions,
265
deleteUser,
266
banUser,
267
promoteUser
268
}, dispatch);
269
}
270
271
return bindActionCreators(baseActions, dispatch);
272
};
273
```
274
275
### Type-Safe Action Creators
276
277
Creating fully type-safe action creators with TypeScript:
278
279
```typescript
280
// Define action types
281
type UserActionTypes =
282
| { type: "SET_USER"; payload: User }
283
| { type: "CLEAR_USER" }
284
| { type: "UPDATE_USER_FIELD"; payload: { field: keyof User; value: any } };
285
286
// Type-safe action creators
287
const userActionCreators = {
288
setUser: (user: User): UserActionTypes => ({
289
type: "SET_USER",
290
payload: user
291
}),
292
clearUser: (): UserActionTypes => ({
293
type: "CLEAR_USER"
294
}),
295
updateUserField: <K extends keyof User>(
296
field: K,
297
value: User[K]
298
): UserActionTypes => ({
299
type: "UPDATE_USER_FIELD",
300
payload: { field, value }
301
})
302
};
303
304
// Bind with full type safety
305
const boundUserActions = bindActionCreators(userActionCreators, store.dispatch);
306
```