Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux Thunk with Typescript

I am learning Typescript and I am trying to implement a simple React/Redux app. When I use sync actions it works fine, but the problems are with the async action. I am following the official redux tutorial.

First I declare the state for the session

export interface UserSessionState {
  loggedIn: boolean;
}

Then I declare the interface for the action

interface UpdateSessionAction {
  type: 'USER_LOGIN';
  payload: boolean;
}

I export them with Union Types

export type UserActionTypes = UpdateSessionAction;

Then I have the actual Action


export function updateSession(loggedIn: UserSessionState) {
  return {
    type: 'USER_LOGIN',
    payload: loggedIn,
  };
}

I have a fake api call

function api() {
  return Promise.resolve(true);
}

And finally the login

export const userLogin = (): ThunkAction<
  void,
  {},
  {},
  AnyAction
> => async (dispatch: ThunkDispatch<{}, {}, AnyAction>) => {
  const res = await api();
  dispatch(updateSession({ loggedIn: res }));
};

In the reducer I simply initialize the state

initialState: UserSessionState = {loggedIn: false}

Then I do the normal redux stuff for the reducer.

Finally in my store I call the initial action for checking the state

store.dispatch(userLogin());

I keep getting this error:

Argument of type 'ThunkAction<Promise<void>, {}, {}, AnyAction>' is not assignable to parameter of type 'AnyAction'.
  Property 'type' is missing in type 'ThunkAction<Promise<void>, {}, {}, AnyAction>' but required in type 'AnyAction'.

I am missing a type but I have no idea what I do wrong.

like image 285
Kaiser Soze Avatar asked Jul 03 '19 14:07

Kaiser Soze


People also ask

Why is redux-thunk better than Redux?

The benefit of Redux-Saga in comparison to Redux-Thunk is that you can more easily test your asynchronous data flow. Redux-Thunk, however, is great for small projects and for developers who just entered into the React ecosystem. The thunks' logic is all contained inside of the function.

Is redux-thunk popular?

Redux-Thunk is the most popular middleware that manages asynchronous actions in Redux.


1 Answers

In short:

You get this error because what returned from your userLogin() function is a ThunkAction, which is missing type

Why this is happening?

dispatch should accept parameter of type AnyAction. AnyAction is a redux type, which extends Action (which have a mandatory property type).

This is from the current redux types file

export interface Action<T = any> {
  type: T
}

/**
 * An Action type which accepts any other properties.
 * This is mainly for the use of the `Reducer` type.
 * This is not part of `Action` itself to prevent users who are extending `Action.
 */
export interface AnyAction extends Action {
  // Allows any extra properties to be defined in an action.
  [extraProps: string]: any
}

How to fix it? Use ThunkDispatch type instead of redux's standard Dispatch. The following example and more can be found on this Gist

const mapDispatchToProps = (dispatch: ThunkDispatch<MyState, void, Action>) => {
  return {
    onRequestClick: (arg: any) => dispatch(myAsyncAction(arg)),
  };
}

Also, see this article, section Map Dispatch to Props

like image 75
yuval.bl Avatar answered Oct 22 '22 22:10

yuval.bl