How to link async action creators using the flowtype method?

I just started to learn flowtype, and I need help to understand two things that are not clear in my mind.

How to continue using threads and binding async action creators when using reducex-thunk?

Sample code ( https://gist.github.com/momsse/323c228e8c5e264067039b8446cd890f ):

 import { bindActionCreators } from 'redux'; import type { Dispatch } from 'redux'; type Action = { type: 'SET_PROFILE', profile: Object }; /** * Based on https://github.com/gaearon/redux-thunk/blob/master/index.d.ts */ type ThunkAction = (dispatch: Dispatch<Action>, getState: () => any, extraArgument: any) => any; type Profile = { name: string, team: string } // Async actions creator function setProfile(profile: Profile): ThunkAction { return dispatch => setTimeout(() => dispatch({ type: 'SET_PROFILE', profile }), 2000); } const profileActionCreators = { setProfile }; type Props = { actions: { setProfile: (profile: Profile) => ThunkAction, } } function mapDispatchToProps(dispatch: Dispatch<Action>): Props { return { actions: bindActionCreators(profileActionCreators, dispatch) }; } 

Errors:

  40: actions: bindActionCreators(profileActionCreators, dispatch) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function call. Function cannot be called on any member of intersection type 40: actions: bindActionCreators(profileActionCreators, dispatch) ^^^^^^^^^^^^^^^^^^ intersection Member 1: 49: declare function bindActionCreators<A, C: ActionCreator<A, any>>(actionCreator: C, dispatch: Dispatch<A>): C; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ polymorphic type: function type. See lib: flow-typed/npm/redux_v3.xxjs:49 Error: 49: declare function bindActionCreators<A, C: ActionCreator<A, any>>(actionCreator: C, dispatch: Dispatch<A>): C; ^^^^^^^^^^^^^^^^^^^^^ function type. Callable signature not found in. See lib: flow-typed/npm/redux_v3.xxjs:49 40: actions: bindActionCreators(profileActionCreators, dispatch) ^^^^^^^^^^^^^^^^^^^^^ object literal Member 2: 50: declare function bindActionCreators<A, K, C: ActionCreators<K, A>>(actionCreators: C, dispatch: Dispatch<A>): C; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ polymorphic type: function type. See lib: flow-typed/npm/redux_v3.xxjs:50 Error: 13: declare type Dispatch<A: { type: $Subtype<string> }> = (action: A) => A; ^^^^^^^^^^^^^^^^^^^^^^^^^^ property `type` of object type. Property not found in. See lib: flow-typed/npm/redux_v3.xxjs:13 21: function setProfile(profile: Profile): ThunkAction { ^^^^^^^^^^^ function type 
+7
javascript redux redux-thunk flowtype
source share
1 answer

These are complete declarations for ActionCreator and bindActionCreators:

  declare type ActionCreator<A, B> = (...args: Array<B>) => A; declare type ActionCreators<K, A> = { [key: K]: ActionCreator<A, any> }; declare function bindActionCreators<A, C: ActionCreator<A, any>>(actionCreator: C, dispatch: Dispatch<A>): C; declare function bindActionCreators<A, K, C: ActionCreators<K, A>>(actionCreators: C, dispatch: Dispatch<A>): C; 

In your code, bindActionCreators will wrap each profileActionCreators property in dispatch . It seems you expect the send to be passed to the setProfile function, where the send can later be used as a callback.

But it doesn’t seem to me that bindActionCreators supports “bind” sending as a callback. Rather, the submission is “linked” as follows:

 function bindActionCreator(actionCreator, dispatch) { return (...args) => dispatch(actionCreator(...args)) } 

So, in your code, it looks something like this:

 function mapDispatchToProps(dispatch: Dispatch<Action>): Props { return { actions: { setProfile: (profile) => dispatch(dispatch => setTimeout(() => dispatch({ type: 'SET_PROFILE', profile }), 2000)), }; } 

Thus, Flowtype correctly detects a type error, stating that bindActionCreators expects each property of the object to be actionCreator: () => Action .

You probably can't use bindActionCreators for your use case, or you need to rethink how you deal with thunks. Here is an approach that should work .

 const profileActionCreators = { setProfile }; type Props = { actions: { setProfile: (profile: Profile) => setTimeout, } } function mapDispatchToProps(dispatch: Dispatch<Action>): Props { const boundActions = bindActionCreators( profileActionCreators, dispatch ); return ({ actions: { setProfile: (profile: Profile) => setTimeout(() => boundActions.setProfile(profile), 2000), }, }); } 

Thunk Approach

If you want to maintain the ThunkAction approach, you cannot use bindActionCreators. This also works.

0
source share

All Articles