preface

In the last article, we covered some of the basics of Redux, the basic implementation, and how to implement synchronous and asynchronous Action and ActionCreator.

If you haven’t read my last post yet, check it out.

Juejin. Cn/post / 696727…

In this post, I will continue with the last demo and show you how to implement thunk middleware. React + Redux + typescript to implement Thunk middleware, but few use connect mode.

In this post, I’ll go into detail on how to implement asynchronous Action and ActionCreator using thunk middleware. Again, this article does not cover how to implement, for beginners, how to implement is not so important, learn to use is the first step! Lol

The Repo address of this Demo is:

Gitlab.com/yafeya/reac…

Installation 0.thunkThe middleware

npm i redux-thunk
Copy the code

1. ModifyClockComponent

In this Demo, based on the previous Demo, we changed the ClockComponent from Promise middleware to Thunk middleware. In fact, there are very few code changes. The main changes are as follows:

  • Action
  • ActionCreator
  • Reducer
  • connectThe second argument to the methodmapDispatchToPropsmethods
  • IndexMiddleware used in

The following is a detailed analysis of these modified points one by one.

2. Detailed analysis

2.1 Action

const FETCHING_TIME = 'FETCHING_TIME';
const FETCHED_TIME = 'FETCHED_TIME';

export interface FetchingTimeAction {
    type: string
};

export interface FetchedTimeAction {
    type: string;
    payload: Date;
}
Copy the code

  • ActionTypeWe went from four to two

    As mentioned in the previous article, the Promise middleware automatically generates three actions for us

    Their types are:

    • *_PENDING
    • *_FULFILLED
    • *_REJECTED

    Then, the Promise middleware was responsible for distributing these three actions to the Reducer, which was beyond our control. But with Thunk middleware, everything is under our control, including the actions that generate several intermediate states and how we dispatch them. So, obviously, we need fewer actionTypes.

    The Thunk middleware is more flexible than the Promise middleware, but it needs to do more of its own work. The Promise middleware has a little more code, but the middleware does most of the work for us. It’s up to you to decide which is better.

  • ActionPayloadfromPromise<Date>Turned out to beDate

    This, and what I think Thunk does a little better, is that Action gets rid of the business logic and becomes a more pure data format, and the business logic goes to ActionCreator.

    Promise

    has business logic, because if the return value has a Promise, its consumer will have to deal with the Promise if it gets a correct result and if it fails, so I say the Promise object is business logic.

2.2 ActionCreator

//Action Creator
export function fetchTime(parameter: string) :ThunkAction<
                                                        // Promise of last dispatched action
                                                        Promise<FetchedTimeAction>,
                                                        // Data type of the last action
                                                        Date, / /The type of the parameter for the nested function
                                                        string, / /The type of last action to dispatch.
                                                        FetchedTimeAction> {
            return async (dispatch: ThunkDispatch<Date.string, AnyAction>) = >{
                console.log(`parameter is ${parameter}`);
                let fetchingAction:FetchingTimeAction = {type: FETCHING_TIME};
                // we can dispatch middle action in the creator.
                dispatch(fetchingAction);
                let time = await getTimeAsync();
                let fetchedTimeAction: FetchedTimeAction = {
                    type: FETCHED_TIME,
                    // property name must be 'payload'
                    payload: time
                };
                return dispatch(fetchedTimeAction);
            };
        };
Copy the code

This is the part that changed the most, so it’s kind of rewritten, just keeping the name of the function, so there’s no comparison, so let’s just analyze the change.

This parameter, you can ignore it, this is what I use for testing, but it doesn’t really mean anything.

  • ThunkAction
    ,>

    • R: Last timedispatchtheActionThe type ofPromiseobject
    E.g. our last 'dispatch' action type was' FetchedTimeAction ', so fill in 'Promise<FetchedTimeAction>' here.Copy the code
    • S: Last timedispatchtheActionThe type ofPayloadtype
    The 'Payload' of 'FetchedTimeAction' is of type 'Date'.Copy the code
    • E: ActionCreatorThe parameter type of the method
    In this example, the parameter of this function is' string ', so I have filled in 'string' here.Copy the code
    • A: Last timedispatchtheActionThe type of
    In this example, the last 'dispath' was' FetchedAction ', so fill this in.Copy the code
  • ActionCreator implementation fetchTime and this method is going to return type ThunkAction

    , and when I first saw it, to be honest, I cracked, what the hell?
    ,s,e,a>

    However, vscode intellisense, is too NB, let’s have a look!

    ThunkAction<R,S,E,A> = (dispatch: ThunkDispatch<S,E,A>) = > R
    Copy the code

    ThunkDispatch

    returns our Promise
    , because R=Promise
    .
    ,e,a>

    Of course, SOME of you, I think, will fill the first argument R with void, but that’s fine, it’s easier.

  • Dispatch the Action we need in ActionCreator

    Believe the above operations, we are a little ring, to be honest, my first time to see, also obtained the along while, but look over one or two times, basically can understand, if you have any questions, then you will remember this is a fixed writing, according to my Demo to set your Action, because the most important we are here to tell, The implementation inside the agent.

    / /...
    console.log(`parameter is ${parameter}`);
    let fetchingAction:FetchingTimeAction = {type: FETCHING_TIME};
    // we can dispatch middle action in the creator.
    dispatch(fetchingAction);
    let time = await getTimeAsync();
    let fetchedTimeAction: FetchedTimeAction = {
        type: FETCHED_TIME,
        // property name must be 'payload'
        payload: time
    };
    return dispatch(fetchedTimeAction);
    / /...
    Copy the code
    • dispatch FetchingTimeAction

      The Reducer will modify isFetching=true in state according to this action, and on UX it can fix isFetching=true, such as showing a progress bar, but we didn’t do any LoL in the demo.

    • callApi

      Call await getTimeAsync(), which is generally slow in real world situations, so this is really asynchronous.

    • dispatch FetchedTimeAction

      When the last call is complete, we can send FetchedTimeAction which Reducer will reduce isFetching=false in state and set succeed=true, and ux will fetch new-state accordingly.

      And the neat thing is that the dispatch(fetchedTimeAction) also returns this Action, which corresponds exactly to the ThunkAction requirement we talked about earlier.

2.3 Reducer

export function clockReducer(state = initState, action: any) :ClockState {
    let result = initState;
    switch (action.type) {
        caseFETCHING_TIME: result = { ... state,isFetching: true
            };
            break;
        caseFETCHED_TIME: result = { ... state,isFetching: false.succeed: true.time: action.payload
            };
            break;
        default:
            result = state;
            break;
    }
    return result;
}
Copy the code

In fact, in a sense, the Reducer logic has not changed, and new states are generated according to different actiontypes. In fact, strictly speaking, only Action and ActionCreator have changed.

2.4 connectThe second argument to the methodmapDispatchToPropsmethods

const mapDispatchToProps = (dispatch: ThunkDispatch<any.any, AnyAction>) = > ({
    fetchTime: (parameter: string) = > dispatch(fetchTime(parameter))
});
Copy the code

The reason for the change here is that the type of the dispatch method has changed to ThunkDispatch.

2.5 IndexMiddleware used in

The smaller change here is to switch the Promise middleware to the Thunk middleware.