In the last video, we introduced some synchronous action creators,
now I want to take advantage of them to handle asynchronous code and to handle asynchronous code, we need
to add a special middleware to our redux project,
a third party library we can add called redux-thunk. Here I'm on the github page, simply google for redux-thunk
written like this to find it, here you can find more instructions on that.
Generally, this is a library which as I just said adds a middleware to your project which allows your
actions to not or your action creators to be precise to not return the action itself but return a
function which will eventually dispatch an action. With this little trick,
not returning the action itself but a function which will then dispatch one,
we can run asynchronous code because the eventually dispatched one part is the part which may run asynchronously,
it'll become clearer once we add it.
So to add it, let's pause or let's quit npm start and let's install a new package with npm install
--save, the name is redux-thunk, written like that.
Now with this, this will get downloaded and stored
as always and we can then register it as a middleware to our project.
Detailed instructions can always be found on the github page of course,
there you see that
after installing it, in the end we just add it with applyMiddleware.
So let's go back into our index.js file where we create the store and add middleware and there, I'll
now import this new package.
So I'll import something from redux-thunk and that something can be found on their page,
they actually have a default export so we don't
need curly bracers, we can give it any name we want,
I'll stick to thunk but you can rename this to whatever you want,
this package essentially just exports the middleware.
Now this already is a middleware,
so behind the scenes it looks like our custom middleware, couple of nested function calls and therefore
we can add it. Now here,
in applyMiddleware
I'll add it
after the logger thunk, so that object we just imported, that function to be precise.
So this is the middleware added, with that we can go back to our action creators in the actions.js
file and let's say in storeResult, we actually want to execute set timeout and only after 2 seconds
we want to store the result.
So here in this function which gets executed, somehow in there, we want to return this action after two
seconds to simulate that we previously or prior to this action reached out to a server to store it there
and only update our state once this one's successful, for example. Now with that, with the current set up
here, this won't work
but with the thunk middleware added, what we can do is we can change this return statement here and
I'll put it right in front of set timeout, we'll clean up the rest here soon,
so I will add a new return statement actually which will return a function, that's important.
Now you can again use the function keyword,
this function receives dispatch as an argument, the dispatch action,
now we get dispatch in here
due to redux-thunk. I said that middleware runs between the dispatching of an action and the point of
time the action reaches the reducer,
now the thing we do here is we still dispatch an action but then redux-thunk, the middleware comes in,
steps in, has access to the action there,
basically blocks the old action we could say and dispatches it again in the future.
Now the new action will reach the reducer but in-between, redux-thunk is able to wait because it can dispatch
an action whenever it wants.
This is the asynchronous part and that is exactly allowing us to execute some asynchronous code inside
of this function
and of course, we can also use good old ES6 arrow syntax here, like this.
So the code inside of this dispatch function here is executed and now inside of set timeout,
inside of this function passed to set timeout, we can execute dispatch to now dispatch whichever action
we want to dispatch.
Now of course, we would create an infinite loop if we again dispatch storeResult here, our action creator.
So what do we typically do is we create asynchronous action creators, which in the end dispatch actions created
by synchronous ones.
So what I'll do is I'll quickly create a new action creator and export it, I'll name it saveResult,
this will now still be the action creator as we had it before receiving the result and there, returning
the action we use previously with type storeResult,
so that is my synchronous action creator. In storeResult
however, I will now dispatch exactly that saveResult action creator which returns me this action
which actually updates the state and the store because it is the action of the type we handle in the
reducer.
Now before we see that in action, we should make the flow clearer,
there's one thing we have to keep in mind, here in storeResult when we return this function which will
get executed by redux-thunk and where we have set timeout, where we then dispatch the action which
should run asynchronously and update the store,
we need to execute saveResult which is this action creator as a function of course and pass res
on
so the redo pass the payload to the store. With that,
make sure to save all files including the counter.js file and then let's restart npm start to see
if this works
and to also see the flow of events in our redux dev tools. So the app loaded, we can still manipulate
our counter but if I click storeResult here,
you see that it took two seconds to actually print storeResult.
Now that's the interesting thing,
you never saw this other action creator
with the set timeout inside of it lead to any output.
If I click storeResult, nothing happens immediately, only after two seconds we see storeResult.
So only the action dispatch in there after two seconds leaves a footprint because it's our synchronous
action and only synchronous actions may edit the store. The other action creators like storeResult
which runs some asynchronous code
are only possible due to redux-thunk and are caught in between,
they never make it to the reducer,
we only use them as a utility step in-between to run our asynchronous code which happens to be required
to run on a lot of actions and then dispatch the synchronous action to change the state in the store
once we are certain that we know what to do there,
so once our asynchronous code finished, this is why we see it here. In the console interesting enough,
where we have our logger middleware, if I clear that, you'll see that we get more output because the logger
logs everything which reaches the action funnel and that includes our function which is returned by
the asynchronous action. We never added the state here though because that gets blocked by redux-thunk.
So this is how we can work with action creators to handle asynchronous code in our redux store.