Home > Back-end >  Error in dispatch async function is not assignable to parameter of type Anyaction in React, Typescri
Error in dispatch async function is not assignable to parameter of type Anyaction in React, Typescri

Time:03-09

I am creating a web application in which I am using firebase as a database, I am using redux and typescript. I made the dispatch inside a callback like this:

export const uploading=(direction:string)=>{
    return async(dispatch:Dispatch,getState:()=>State)=>{
        const {active} = getState().dates;
        const ss = await getSS(direction);
        active.home = ss;
        dispatch(save(active));
    };
};

and the error I get is the following:

Argument of type '(dispatch: Dispatch, getState: () => State) => Promise<void>' is not assignable to parameter of type 'AnyAction'.    Property 'type' is missing in type '(dispatch: Dispatch, getState: () => State) => Promise<void>' but required in type 'AnyAction'.

and the function that appears in the dispatch is the following:

export const save = (dates:Dates) => {
    return async(dispatch:Dispatch,getState:()=>State) => {
        const { uid } = getState().auth;
        const dateToSave = {...date,id:""};
        const dateToFirestore = doc(db,`${uid}/dates/${dates.id}`);

        try{
            await updateDoc(dateToFirestore,dateToSave);
            dispatch(refreshDate(date.id,date));
            console.log("ok")
        }catch(error){
            console.log(error)
        }
    };
};

Now, if I don't do the dispatch from an async function I don't have any problem, in fact I was already doing it to save new data, but when I try to call it from the aforementioned function I get the error.

My store

import {combineReducers,compose,createStore,applyMiddleware} from 'redux';
import thunk from 'redux-thunk';

import {authReducer} from '../reducers/authReducer';
import {uiReducer} from '../reducers/uiReducer';
import {datesReducer} from '../reducers/datesReducer';

const reducers = combineReducers({auth: authReducer,ui: uiReducer,dates: datesReducer});

const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__||compose;

export const store = createStore(
    reducers,
    composeEnhancers(applyMiddleware(thunk))
);

I want to add some information, I tell you, if I dispatch a normal Action there is no problem, that is, an action that does not return an async function

CodePudding user response:

From redux store.ts

import { AnyAction } from 'redux';

return async(dispatch: Dispatch<AnyAction>, getState: () => State)
// rest of your code

or using ThunkDispatch imported from redux-thunk

import { AnyAction } from 'redux';
import { ThunkDispatch } from 'redux-thunk';

// Types to cut down on boilerplate across dozens of thunks.
type Dispatcher = ThunkDispatch<State, undefined, AnyAction>;
type GetState = () => State;

return async(dispatch: Dispatcher , getState: GetState)
// rest of your code

Here is a few thoughts of redux maintainer on writing typescript

It feels like a number of TS users would rather spend hours trying to come up with unreadable and incredibly complex type declarations, rather than solving real problems and shipping code that does something useful

I think its true when we first time do typescript, slap it with any ^^ mark it with FIXME and move on to next task

CodePudding user response:

Especially when using TypeScript, you should be using the official Redux Toolkit. Even the JS code gets cut at least in half, but you save almost all of the TS type declarations traditional Redux would have.

Also, and that is more to the point of this question, there is explicit documentation on how to set that up to be used with TypeScript, including defining specific useAppDispatch hooks that take the types of all Redux middleware (including thunk) into account.

In this case:

import { configureStore } from '@reduxjs/toolkit'
import { useDispatch } from 'react-redux'
import rootReducer from './rootReducer'

const store = configureStore({
  reducer: rootReducer,
})

export type AppDispatch = typeof store.dispatch // you can use this Dispatch type in your thunks
export const useAppDispatch = () => useDispatch<AppDispatch>() // Export a hook that can be reused to resolve types

export default store
  • Related