Redux Toolkit - Argument of type 'AsyncThunkAction<>' is not assignable to parameter of type 'AnyAction'

Viewed 7807

I'm moving my React / Redux application to Redux toolkit, and am following instructions given here.

My custom selector and dispatch, as per the documentation.

import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import { AppDispatch, RootState } from "@/index";

export const useMyDispatch = () => useDispatch<AppDispatch>();
export const useMySelector: TypedUseSelectorHook<RootState> = useSelector;

Type of useMyDispatch is useMyDispatch(): Dispatch<AnyAction>

Type GETALLPAGESACTION is

export type GETALLPAGESACTION = {
  pagesLoading?: boolean;
  pages?: PageType[] | null;
  error?: Error | null;
}

This is my very basic action:

export const getAllPages = createAsyncThunk<GETALLPAGESACTION, 
 string,
 { dispatch: AppDispatch; state: RootState; }>("pages/getAllPages", 
   async () => {
   const pagesRes = await axios.get("___");
   if (pagesRes) {
     const finalPages: PageType[] = [];
     pagesRes.data.forEach((page: PageType) => {
     finalPages.push(page);
   });
   return { pages: finalPages, pagesLoading: false };
 }
 return { pages: [], pagesLoading: false };
});

My store is a simple:

const appStore = configureStore({
  reducer: {
    pages: PagesReducer, // pagesSlice.reducer is default export
  },
});
export type RootState = ReturnType<typeof appStore.getState>;
export type AppDispatch = typeof appStore.dispatch;

But when I try to use getAllPages in my component I get the above error.

useEffect(() => {
  dispatch(getAllPages());  // Error here 
 }, []);

Argument of type 'AsyncThunkAction<GETALLPAGESACTION, string, { dispatch: Dispatch<AnyAction>; state: { pages: { pages: null; pagesLoading: boolean; }; }; }>' is not assignable to parameter of type 'AnyAction'.

I know this question has been asked several times, and I have tried adding those solutions, including trying to set an explicit middleware type, which controls the dispatch type, but none of that has worked. From what I can understand (I'm relatively new to Typescript), the dispatch type is not being inferred correctly here?

This is my slice

export const pagesSlice = createSlice({
  name: "pages",
  initialState,
  reducers: {},
  extraReducers: {
    [getAllPages.pending]: (state, action: PayloadAction<GETALLPAGESACTION>) =>   {
      state.pagesLoading = true;
    },
    [getAllPages.fulfilled]: (state, action: PayloadAction<GETALLPAGESACTION>) => {
      state.pages = action.payload.pages;
      state.pagesLoading = false;
    },
   [getAllPages.rejected]: (state, action: PayloadAction<GETALLPAGESACTION>) => {
      state.pagesLoading = false;
   },
 },
});
export default pagesSlice.reducer;

I could really use some help here, especially with an explanation of what is wrong here and what I should dig into further to understand this better. Thanks!

2 Answers

Most of the time this is just a bug, caused by Redux 4.0.5 and Redux 4.1.0/4.1.1 being installed both somewhere in your node_modules.

Most of the time, this can be resolved by reinstalling react-redux, @types/react-redux and @reduxjs/toolkit.

If you are using yarn, you can also run yarn why redux and it will list you all installed versions and why they are installed.


Update June 2022:

The same also happens if you install react-redux in v.8 and still have @types/react-redux in v.7 installed. react-redux 8 ships with it's own type definitions - in that case please uninstall @types/react-redux.

In my case I had to create useAppDispatch function and use it instead useDispatch in component from react-redux.

export type AppDispatch = typeof store.dispatch

export const useAppDispatch = () => useDispatch<AppDispatch>()
Related