Using the AppDispatch type in Redux async thunk: A comprehensive guide

While working with my Redux async thunks, I encountered a situation where I needed to utilize the AppDispatch type as outlined in this resource: https://redux.js.org/recipes/usage-with-typescript

Following the guidelines provided here: https://redux.js.org/recipes/usage-with-typescript#typing-createasyncthunk

However, incorporating the AppDispatch type within my custom ThunkApiConfig type (MyThunkApiConfig in the code example) resulted in a circular reference issue demonstrated in this example: https://codesandbox.io/s/focused-joliot-ho45h?file=/src/usersSlice.ts:

'dispatch' is referenced directly or indirectly in its own type annotation.

This dilemma arises from the circular dependency between the dispatch type and the used thunks. I am seeking advice on how to effectively implement AppDispatch within the async thunk functionality. Any insights would be greatly appreciated!

Answer №1

Using AppDispatch in your MyThunkApiConfig type is perfectly fine. The issue arises when this is combined with defining the slice as a function of the async action, creating an unwanted coupling between slice types and dispatch types.

If the reducer is usersSlice.reducer, there is no problem. This setup utilizes the updateUser async thunk which relies on typed dispatch. However, the slice type remains independent of the dispatch type, focusing solely on state and actions.

In contrast, using MyThunkApiConfig in createAsyncSlice leads to a circular dependency between store and slice types.

The concept of passing the updateUser async thunk through a function instead of directly seems unclear. The simple solution would be to avoid doing so.


If you wish to directly assign the type for

AppDispatch</code, it is possible but not recommended due to its complexity and reliance on generic type parameters.</p>
<pre><code>export type RootState = { users: UsersState }
export type AppDispatch = Dispatch<AnyAction> & ThunkDispatch<RootState, null, AnyAction> 

In your example, omitting MyThunkApiConfig altogether is viable. Generics can be dropped from updateUser as they will default to <User, void, {}>. Typing the slice argument as

asyncThunk: AsyncThunk<User, void, {}>
resolves the circular typings issue.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can an attribute be assigned to an Angular host element without specifying a value?

Exploring the concept of host binding on the input element's readonly attribute, aiming to add the attribute without assigning any value. Even though HTML specifications state that assigning a value may not make a difference as long as the attribute i ...

elimination of nonexistent object

How can I prevent releasing data if two attributes are empty? const fork = [ { from: 'client', msg: null, for: null }, { from: 'client', msg: '2222222222222', for: null }, { from: 'server', msg: 'wqqqqqqqq ...

What methods does Angular use to determine the parameter types of a constructor?

I've been experimenting with replicating Angular's approach to interpreting the constructor in an injectable service. function Injectable() { return function<T extends { new (...args: any[]): {} }>(con: T) { return class extends con ...

Tips for customizing the appearance of a redux-tooltip

After implementing the redux-tooltip from this GitHub repository, I wanted to customize its styling to better align with my application's design. However, I realized that the Tooltip-Component's divs do not have any identifiers or class names, ma ...

Typescript's ability to have Enums with dynamic keys

Suppose I define: enum Sort { nameAsc = 'nameAsc', nameDesc = 'nameDesc' } Is it possible to do the following? const key = 'name' + 'Desc'; Sort[key] Appreciate any help in advance ...

gather and handle data from the shared interface between different parts

I have two different paths. One is for products and the other is for products-cart. I want to use a shared ts file for both to store the product and cart information in an array. However, I am encountering an issue. I am unable to make any changes or trans ...

Is it possible to place Angular Material components using code?

Currently, I'm in the process of creating a responsive Angular application. Is there any way to adjust the height and position of the <mat-sidenav-content></mat-sidenav-content> component in Angular Material programmatically without relyi ...

Is there a way to create a TypeScript function that can accept both mutable and immutable arrays as arguments?

Writing the following method became quite complicated for me. The challenge arose because any method receiving the result from catchUndefinedList now needs to handle both mutable and immutable arrays. Could someone offer some assistance? /** * Catch any ...

Creating efficient React components with TypeScript and leveraging generic props

I’ve been working on understanding and resolving my issue with React components' generic props. I came across a code example in an article about using TypeScript with functional React components and generic props. Unfortunately, when trying to repli ...

When no values are passed to props in Vue.js, set them to empty

So I have a discount interface set up like this: export interface Discount { id: number name: string type: string } In my Vue.js app, I am using it on my prop in the following way: export default class DiscountsEdit extends Vue { @Prop({ d ...

Utilizing References in React Components

One of the challenges I am facing involves a Container that needs references to some of its child components: const Container = () => { const blocks: HTMLDivElement[] = []; return ( <div> <Navigation currentBlock={currentBlock} ...

Unable to retrieve this information within an anonymous function

I am currently working on converting the JSON data received from an API interface into separate arrays containing specific objects. The object type is specified as a variable in the interface. Here is the interface structure: export interface Interface{ ...

Retrieving the Final Value from an Observable in Angular 8

Is there a way to retrieve the most recent value from an Observable in Angular 8? let test = new BehaviorSubject<any>(''); test.next(this.AddressObservable); let lastValue = test.subscribe(data=>console.log(data.value)); Despite my ef ...

Attempt the HTTP request again only for specific status codes

When developing my Angular application, I encountered a situation where I needed to make an HTTP call to a backend server. To enhance its reliability, I decided to incorporate an interceptor to implement the retry pattern. In the past, I utilized RxJS&apo ...

Guide to implementing ES2022 modules within an extension

After making changes in my extension code to test various module types, I decided to modify my tsconfig.json file as follows: { "compilerOptions": { "declaration": true, "module": "ES2022", ...

Is there a way for me to add a clickable link within a tooltip?

In my title, I want to insert a clickable link like 'Link' or 'a'. The title is ready for any string you input. <MaterialSwitch title={CLICKABLE STRING HERE} /> ...

Can you explain the significance of the colon in this context?

Upon reviewing some SearchKit code snippets (composed with react/jsx and es2015), I came across the following line in a jsx file: const source:any = _.extend({}, result._source, result.highlight) I am curious about the purpose or significance of the colo ...

When implementing a TypeScript interface, there is no method parameter checking performed

interface IConverter { convert(value: number): string } class Converter implements IConverter { convert(): string { // no error? return ''; } } const v1: IConverter = new Converter(); const v2: Converter = new Converter(); ...

Issue detected: Props that are of type Object/Array must utilize a factory function in order to provide the default value

I recently started using Vue-Cli3.0 and came across this interesting module for Vue.js called https://github.com/holiber/sl-vue-tree It's a customizable draggable tree component for Vue.js, but I encountered an issue where it couldn't copy funct ...

Trouble arises when trying to test an Angular service that relies on abstract class dependencies

Currently, I am working on a service that has a dependency on another service, which in turn relies on two abstract classes as dependencies. (ThemeConfigService -> (SettingsService -> SettingsLoader, NavigationLoader)) During testing, the failure oc ...