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.thunk
The 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
connect
The second argument to the methodmapDispatchToProps
methodsIndex
Middleware 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
ActionType
We 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.
ActionPayload
fromPromise<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 time
dispatch
theAction
The type ofPromise
object
E.g. our last 'dispatch' action type was' FetchedTimeAction ', so fill in 'Promise<FetchedTimeAction>' here.Copy the code
- S: Last time
dispatch
theAction
The type ofPayload
type
The 'Payload' of 'FetchedTimeAction' is of type 'Date'.Copy the code
- E:
ActionCreator
The 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 time
dispatch
theAction
The type of
In this example, the last 'dispath' was' FetchedAction ', so fill this in.Copy the code
- R: Last time
-
ActionCreator implementation fetchTime and this method is going to return type ThunkAction
,s,e,a>
, and when I first saw it, to be honest, I cracked, what the hell?
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
,e,a>
returns our Promise
, because R=Promise
.
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.
- call
Api
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 connect
The second argument to the methodmapDispatchToProps
methods
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 Index
Middleware used in
The smaller change here is to switch the Promise middleware to the Thunk middleware.