Best practice of Redux promise Middleware

Time:2021-5-9

Overview of Redux promise Middleware

We have discussed middleware before. aboutreduxThe middleware we use to deal with asynchrony isredux-promise-middlewareCompared withredux-promiseIt retains the ability to update optimistically. After enabling it, we can trigger apayloadProperty ispromiseObjectaction

const foo = () => ({
  type: 'FOO',
  payload: new Promise()
})

The middleware immediately triggers aaction, type is the type we declare plus_PENDINGWe can configure the suffix ourselves

{ type: 'FOO_PENDING' }

etc.promiseThe state of the object changes(resolvedperhapsrejected), middleware triggers anotheractionAnd carry it with youpromiseIt’s a good information.

{
  type: 'FOO_FULFILLED'
  payload: { ... }
}

{
  type: 'FOO_REJECTED'
  payload: { ... }
}

Implementation principle

About itSource codeIn fact, it’s easier to understand, just to judgeactionOfpayloadattribute

if (action.payload) {
   if (!isPromise(action.payload) && !isPromise(action.payload.promise)) {
     return next(action);
   }
 } else {
   return next(action);
 }

If it ispromiseObject to trigger an asynchronous startaction

next({
    type: [type, _PENDING].join(promiseTypeSeparator),
    ...(data !== undefined ? { payload: data } : {}),
    ...(meta !== undefined ? { meta } : {})
});

And wait for thispromiseAfter the state of the object is changed, a different trigger is triggered according to whether it is successful or notactionAnd carry the data or error message. Combined with the author’s notes, it is easy to understand.

Practice analysis

In practice, almost every asynchronous operation needs to increase its optimistic update ability, even a simple onebuttonIt will also need to have aloadingState, on the one hand, gives users a better experience, on the other hand, it also prevents repeated requests.

But for the sake ofreduxUsing this state in, it’s inevitable to target each asynchronous stateactionTo declare many variables to maintain the value of this variable. as follows

switch (action.type) {
    case 'MY_ACTION_TYPE_PENDING':
        return {...state, myActionLoading: true}
    case 'MY_ACTION_TYPE_FULFILLED':
        return {...state, xxx,  myActionLoading: false}
    case 'MY_ACTION_TYPE_REJECTED':
        return {...state, myActionLoading: false}
}

We’ve written a lot of this repetitive code to do the same thing, since each of usactionOftypeThey’re all unique. Why not make a general method to deal with the maintenance of this state base.

If we make a special statementreducerTo handle state change events. modifyredux-promise-middlewareWhen an asynchronous event starts or the state changes, we trigger not only the original event, but also a special eventaction, which carries thetypeandstateAs a parameter, when we receive this event, we put thereducerCorrespondingtypeThe state of the parameter is changed to the state of the parameter. So we can update each one automaticallyactionThe current status value is too high.

//The reducer is similar to the following
//Statemessage refers to the ` action's type corresponding to a special event`
import { STATEMACHINE } from 'redux-promise-middleware'

const uiStateStore = (state = {}, action) => {
    switch (action.type) {
        case STATEMACHINE: {
            let { actionType, isFetching } = action
            return {
                ...state,
                [actionType]: isFetching
            }
        }
        default:
            return state
    }
}


<Button
      loading={this.props.isLoading} />

...

const mapStateToProps = state => ({
    ...,
    isLoading: state.uiState.MY_ACTION_TYPE
})

The effect is as follows

Best practice of Redux promise Middleware

It can be used in the projectreact-ggsddufunctionnpm run async-2Experience.

Blog address