Redux Thunk
By Redux team
Redux Thunk is a middleware for Redux that allows action creators to return a function instead of a plain action object, enabling asynchronous logic such as API calls to be written directly inside that function before dispatching real…
Definition
Redux Thunk is a middleware for Redux that allows action creators to return a function instead of a plain action object, enabling asynchronous logic such as API calls to be written directly inside that function before dispatching real actions. It is the simplest and most widely adopted way to handle async logic in Redux applications and ships as the default middleware in Redux Toolkit.
Overview
Redux Thunk was created to solve a basic limitation of vanilla Redux: the dispatch function only accepts plain action objects, but real applications frequently need to perform asynchronous work, like fetching data from a server, before an action with the fetched result can be dispatched. Redux's synchronous, plain-object-only design gives no obvious place to put that asynchronous logic without middleware support. Redux Thunk's mechanism is intentionally minimal: the middleware inspects each dispatched value, and if it is a function rather than a plain object, the middleware calls that function with dispatch and getState as arguments instead of passing it to the reducers. This lets a thunk action creator return a function that can perform an async operation, such as an API call, and then call dispatch one or more times as the operation progresses, for example dispatching a loading action immediately and a success or failure action once the request resolves. Because the thunk function receives getState, it can also read current state before deciding what to dispatch, enabling simple conditional logic like avoiding a duplicate fetch if data already exists in the store. Compared to redux-saga or Redux Observable, thunk trades expressive power for simplicity: it has no built-in support for cancellation, racing, or debouncing, and complex coordination between multiple async operations must be hand-written using promise chaining or async/await inside the thunk function itself. This makes thunks straightforward to learn, since they require no new concepts beyond functions and promises, but they can become unwieldy for very complex flows where saga-style declarative effects would be clearer. In practice, redux-thunk is the default choice for the majority of Redux applications, particularly since Redux Toolkit bundles it automatically and layers createAsyncThunk on top of it to standardize the loading and pending or fulfilled or rejected action pattern that hand-written thunks previously required boilerplate to implement. Developers use it for straightforward data fetching, form submission, and any async flow that does not require cancellation or complex race conditions. The main limitation of redux-thunk is exactly its simplicity: as an application's async requirements grow to include cancellation of stale requests, coordinating multiple concurrent operations, or complex retry and backoff logic, hand-written thunk code tends to accumulate ad hoc solutions to problems that saga-based or observable-based middleware solve declaratively. Teams should treat the appearance of significant async complexity as a clear signal to consider adopting redux-saga rather than continuing to extend ad hoc thunk logic indefinitely.
Key Features
- Allows Redux action creators to return functions instead of objects
- Provides dispatch and getState to the returned thunk function
- Ships as the default middleware in Redux Toolkit
- Requires no generators, observables, or new syntax to learn
- Pairs with createAsyncThunk for standardized async action patterns
- Supports conditional dispatch based on current store state
- Handles simple sequential async logic with async/await