‫Let's now use Redux Thunks
‫to implement a feature where the user can deposit money
‫into the account in a foreign currency,
‫which will then be converted by calling an external API.
‫So basically, whenever the user deposits some money here,
‫they can select which currency that money is.
‫So for example, euro.
‫And so if that currency is different from US dollar,
‫then we need to convert these 500 euros back to US dollars
‫before they actually get deposited into the account.
‫So before that deposit action is actually dispatched
‫to the store.
‫And so that's where now the Redux thunk comes into play.
‫So we will have that middleware sitting
‫between dispatching the action,
‫as we click here on the button,
‫and that action actually reaching the store.
‫Okay?
‫So in order to use this middleware,
‫we need to follow three steps.
‫First, we install the middleware package.
‫Then we apply that middleware to our store.
‫And finally, we use the middleware
‫in our action creator functions.
‫So let's now do them one by one.
‫So down here, let's say
‫npm install redux-thunk.
‫Okay.
‫And so then we can import
‫the thunk function, basically,
‫from redux-thunk that we just installed.
‫Not think, of course.
‫And here. Okay.
‫So we installed and brought that thunk in,
‫and so now we need to apply that to our store.
‫So here, in the createStore function,
‫we can pass in another argument.
‫And now here, we need to call the applyMiddleware function.
‫So applyMiddleware, which is also provided by Redux itself.
‫So see how that got imported here?
‫And now into this applyMiddleware function,
‫we pass in our middleware.
‫And so that is the thunk.
‫And so with this, we basically told Redux,
‫or we told our store,
‫that we want to use the thunk middleware in our application.
‫And so let's now go to the action creator
‫that is actually responsible for depositing money
‫in the account.
‫Now here, we lost our account.
‫So there we go.
‫But as I was saying,
‫now let's come into the account slice,
‫and in particular, here into this deposit action creator.
‫So here, besides accepting the amount,
‫we now also will need to accept the currency.
‫So as we dispatch the action of deposit,
‫we will not only pass in the amount, but also the currency.
‫And so let's actually immediately do that.
‫So right here.
‫So handleDeposit,
‫this is where we dispatch this action.
‫So where we call this action creator.
‫And so here now, we also need the currency.
‫And then let's also clear the currency
‫since we're already here.
‫And so that's it for now.
‫So again, now our action creator receives
‫not only the amount that should be deposited,
‫but also the currency that that amount is in.
‫Now, first of all,
‫if that currency is already US dollars,
‫so if that's USD,
‫and these values, they come right here
‫from these option values.
‫So we have USD for US dollars,
‫we have euro, and we have British pounds.
‫So these can be the three currencies.
‫So again, if the currency already is US dollars,
‫then there's nothing to convert.
‫And so then we can simply return the object,
‫so this action, just like before.
‫So in this case, nothing is going to change.
‫But if the currency is different,
‫then this is where we will need to make that API call.
‫And so for that, we need the thunk.
‫Now, this middleware is, in our code,
‫actually nothing special.
‫So the only thing that changes is that here,
‫in this action creator,
‫we will not return the action immediately,
‫but instead return a function.
‫So we can now return
‫a function like this.
‫And so then here,
‫when we dispatch right here
‫and then call the deposit action creator,
‫instead of ending up with the event object right here,
‫we will end up with a function.
‫So basically, we will dispatch a function.
‫And so when Redux sees that,
‫it will know that that function is the thunk.
‫And so it will then execute that function
‫and not immediately dispatch the action to the store.
‫All right?
‫So again, if we return a function here,
‫then Redux knows that this is the asynchronous action
‫that we want to execute before dispatching anything
‫to the store.
‫Now, in order to then later actually dispatch,
‫this function here that Redux will call internally
‫will get access to the dispatch function
‫and to the current state.
‫So by calling the getState function.
‫All right?
‫And so then here we can do our API call.
‫And then once we are finished with that,
‫we can then finally, in the end, return the action.
‫So this is where we will return the action in the end.
‫All right? And so let's do that API call here.
‫And we already used this API before.
‫So let's just grab the URL here
‫from the frankfurter.
‫And here it already is.
‫So like this.
‫And then you can just click here on Documentation.
‫And then all the way in the end,
‫we have this URL right here
‫from which we are going to fetch.
‫So just copy that.
‫And then here, let's do the fetch request.
‫And now here, we don't have the host,
‫so let's just grab this part here as well
‫and place that here.
‫All right.
‫Now here, we, of course, now need to replace these values
‫so the amount is the amount that we actually get.
‫So amount, and then from is this currency that we receive,
‫and the to currency is US dollars.
‫Now, of course,
‫we could also have defined the target currency
‫in the state, for example.
‫So we could create also here the currency
‫that the account is in.
‫And so then here we would have to check that.
‫But let's, once again, just keep it simple here.
‫All right.
‫Now, not sure why I have two fetches here.
‫But anyway, we will want to await this
‫and then the store the result
‫into the res variable.
‫And so then we make this an async function.
‫Okay?
‫Then, as always,
‫we need to await the conversion to JSON.
‫And then let's take a look at the data first.
‫And so this should, at this point, already be working.
‫So let's test this.
‫This is not really important here.
‫And so let's deposit 100.
‫And let's say that we are depositing 100 euros.
‫So let's click here.
‫And so, indeed,
‫our function here was now called,
‫and it logged to the console these results.
‫So we are interested in here is these rates
‫and then that USD.
‫So let's just store that as well.
‫So converted is data.rates.USD.
‫All right?
‫And so now we have the value
‫that we actually want to dispatch to the store.
‫And so now we will return our action.
‫So basically, exactly what we had here before.
‫So the action type is the same,
‫and the payload will now no longer be the amount,
‫but the converted amount.
‫And so with this,
‫we did now in fact delay the creation
‫of the action to the future.
‫So basically to the point after this fetch request here
‫has successfully retrieved the data.
‫So only after all of this is done, we actually dispatch.
‫So actually, it is not returned here, but really dispatched.
‫So here we no longer need to return, but really to dispatch.
‫And so that is the reason why we get access
‫to the dispatch function right here.
‫And so now we basically have two dispatches.
‫So first we dispatch here,
‫and in the case we have another currency
‫that is not US dollars,
‫then this will return a function, right?
‫So this function right here.
‫And so then Redux will call this function
‫and pass it the dispatch function
‫so that we can then call that function in the future
‫when we want to actually dispatch our action
‫in the end to the store.
‫So when we already have the result
‫of the asynchronous operation.
‫And so this should now actually work nicely.
‫So let's then deposit 100 euros.
‫And beautiful.
‫This is exactly what 100 euros converted
‫to US dollars is right now.
‫And of course, you will see a different value here,
‫but what matters is that this worked now.
‫And so if we think about this,
‫then this entire code here,
‫what is essentially our middleware,
‫really sits between the dispatching and the store.
‫So when we dispatch the action
‫and the currency is different from US dollar,
‫then that action never actually reaches the store,
‫at least not in the beginning,
‫because instead, then this code here will be executed.
‫And only after that is finished,
‫we then dispatch a new action to our store
‫with the new value.
‫And so, again, this really sits then in the middle.
‫And so therefore the name middleware.
‫And now, just to finish,
‫let's also show the user some loading indicator.
‫So telling them
‫that some asynchronous operation is happening.
‫So to do that, let's create a new state here.
‫And as always, let's call that isLoading,
‫which in the beginning will, of course, be false.
‫But then, as soon as we start fetching,
‫let's then actually dispatch an action
‫that will set isLoading to true.
‫So basically, right before here.
‫So we can do dispatch.
‫And then the type of the event,
‫let's call it account
‫and then convertingCurrency.
‫And so you see that we really can dispatch actions
‫as we please right here in this middleware.
‫So we don't have to limit ourselves
‫to only doing that here in the end.
‫So here, we will dispatch immediately
‫to let the user know that we are doing some work,
‫and then in the end, as soon as we're done with that work,
‫we dispatch the new value into the store.
‫So then it reaches our reducer.
‫And so now let's then implement
‫that new action right here.
‫So that's account/convertingCurrency,
‫I believe.
‫And so here, all this does is to return the current state
‫and set isLoading to true.
‫Okay?
‫And so now, in the end,
‫do you think that in the end,
‫we should then here dispatch another action,
‫so one to basically set isLoading back to false?
‫Well, we don't have to
‫because that's the beauty of updating multiple states
‫at the same time with the reducer.
‫So all we have to do is to come here into deposit
‫and then set the isLoading
‫to false right here.
‫And so now all we have to do
‫is to then get that from the state.
‫So from here,
‫isLoading, and then we can use that right here,
‫close to the button.
‫So here, we can use the disabled prop
‫and set that to isLoading.
‫And so then whenever this is true,
‫we will not be able to click on that button.
‫And then here, inside the text,
‫let's do some conditional rendering.
‫So let's say if isLoading,
‫then let's say converting.
‫And else, then here,
‫we need a template literal,
‫just like this.
‫So let's check again with our 100 euros.
‫And that was really fast,
‫but I think the text changed here shortly.
‫So let's come to our Network tab
‫and do some throttling
‫with a slow 3G maybe,
‫and then let's try that again.
‫So I always like to do that.
‫Well, that's still very fast.
‫So I guess that API is a fast one.
‫But yeah, let's just trust
‫that everything works this way.
‫Okay?
‫Now, the beauty of what we just implemented here is
‫that this component here actually has no idea
‫that the amount is converted behind the scenes.
‫So that conversion is completely hidden from our component.
‫And instead, it is encapsulated right here
‫in the account slice.
‫So it's happening here in the centralized place.
‫And if we had other API calls
‫or other asynchronous operations
‫in these other action creators,
‫then, of course, they would also be in this file.
‫So again, they would then all be
‫in this one centralized place,
‫not spread all over the application.
‫And so with this,
‫we can keep this component here really tidy and clean.
‫I mean, it's not really that clean
‫because we chose to have all this JSX in one file,
‫which usually we would probably split up.
‫But you get the point.
‫So we don't have the data fetching anymore here
‫in the component.
‫So I hope this wasn't all too confusing.
‫And what I mostly want you to retain
‫is that when we are using Thunks,
‫instead of returning an action object
‫from the action creator function,
‫we return a new function.
‫And so then the result of this becomes a function
‫and no longer an object.
‫And so then Redux,
‫when it sees that we are dispatching a function,
‫it will call that function,
‫and into that function,
‫it'll pass in the dispatch function and getState,
‫which we didn't even use, in this case.
‫And so then we can use that dispatch function
‫inside here to delay that dispatching
‫until the asynchronous operation
‫that we want to implement has finished.
‫And so therefore, we can think of this function here sitting
‫between the initial dispatching and the reducer
‫in the store receiving the action.