Async Redux — How to use Thunk Middleware

Intro:

Phase 5!!!!!!!!!! Oh my Gosh WOW! SO I made it to the 5th phase Of Flatiron School, I’ve yet to take my assessment but I’m praying I get through!

Anyways What I want to talk to you about in my final blog for Flatiron is Asynchronous Redux and How to use the Thunk Middleware. This one really threw me off when I first learned it, but from a lot of coding and studying I think i finally got it!! AND hopefully writing this blog I’ll have even more practice before my final FINAL Assessment!!

GOAL of Async Redux

The goal when we use asynchronous logic in redux is to take any asynchronous logic such as a fetch() request, and moving it from our React side to our Redux side.

THUNK:

Thunk is a middleware that’s going to allow us to interact with our API in Redux rather than just interact with our API in the UI. This too, is more about design patterns and where we want to have what code, separation of concerns, rather than you have to use thunk in a React app using Redux.

App Flow: From our UI we’re looking at our state from our store and THEN my UI can make a change. THEN what we’re going to allow ourselves to do with this async logic is give “Dispatch” the functionality of being able to call a function instead of just an Action Object, so that it can send a FETCH request. WHICH will interact with my API and then bring in our action object.

A “THUNK” is a function that allows us to think later again later on. Any function that wraps an expression to delay its evaluation you can consider a Thunk.

`` ` const numbers = 7 * 8–5 + 7 const func = () => 7 * 8–5 + 7 ```

The “func” function above is a THUNK — func allows me to call on it later on at any point and evaluate it when I call it. In other words, By making it a thunk I’m allowing the func expression to be evaluated at a later date.

When you bring in the Library REDUX THUNK (type into terminal to install):

```yarn add redux-thunk```

you can see that theres a little more to it, it’s 14 lines of code, that’s all it is, this little library that we’re going to be pulling in to work with REDUX.

You can see here we get a function createThunkMiddleware with an extra argument. We’re not going to be dealing with this, you can ignore the extra argument for now. This function returns another function that takes in DISPATCH, and getState() that will be passed in by my “store” ( these functions are products of my store). THEN we get another function thunk returns, this function takes in “next”, you can think of “next” as our default behavior. “next” is what happens when I usually DISPATCH an action (in basic redux) and it’s sent to my reducer to return a new state. If you look at this part:

Think of this as DISPATCH, this is what we actually pass into DISPATCH here. With Dispatch we pass in arguments of our action objects — Ok WHat’s going on here is THUNK is checking “if our action we passed in is a function it’s going to call that function here:

And pass in a couple extra arguments — We’re only going to be working with the first argument here “dispatch”, by using our action as functions that take in DISPATCH as a function. Otherwise it’s just going to do the default behavior and imagine that my action here is my object ```return next(action)```, this is what we’re used to in basic Redux — an “action object” that would go to my Reducer and then update my Store. Here in ```return next(action)``` we can still decide on our own to pass them the plain old action objects — ```dispatch({type: “ADD_ITEM```, payload: item})```. It just does this extra behavior with the “if statement” if it’s a function.

Basically what Thunk is going to allow us to do is pass DISPATCH a function, this function will take in “dispatch” as an argument ```dispatch => {} ```. Then we’ll be able to add whatever functionality we want, eventually return an action object in here, and dispatch an action object. NOTE: what we’ve been doing in basic redux is writing our dispatches to take in an object directly ```dispatch(type: “ADD_ITEM”, payload: item()```.

*In a shorter description, “THUNK is going to allow us to pass dispatch a function or a callback rather that just passing it an “action object”. — Example: using a FETCH request so that we can pass dispatch callbacks rather than just plain old action objects.

Passing Thunk to our Store:

Store.js — where we want to import in createStore() — WHICH is coming from the redux library — this has nothing to do with REACT yet — It”S a function that we’re going to pass in a “reducer” — export default this as well

Then we’re going to be passing our middleware to our store. So we need to pass “applyMiddleware” as our second arg after our reducer. Finally we can then pass to our applyMiddleware argument “thunk” — NOTE: remember to import in your thunk from redux-thunk at the top of your file:

Store.js

applyMiddleware comes from REDUX, we can use it as our third argument, but since we’re not passing in our initialState, it’s passed in as our second argument here for any enhancers or middleware that we want to include. Again this is a function that comes from the redux library, then we’re also importing that code from thunk — the 14 lines of code that’s going to allow us to pass dispatch a callback rather than just passing dispatch an action object.

Setting up our Store inside index.js

To access our store throughout our App/connect our React to our Redux, we can set up our store in index.js. We’re not importing store anywhere, it’s only going to be used inside <Provider>. <Provider> is specific to react-redux code it’s how we’re connecting react to redux, connect() is also how we’re connecting the two (from the react-redux library). ALL we need to do inside store.js is export the return value of createStore so we can import it into index.js and pass it as a PROP to my <Provider> component.

Before we set up store in our index.js, we need to make sure we have our Reducer created:

CREATE reducer.js file, you can use combine reducers and use multiple reducer. Reducer is a function that takes two args state and action, usually the action would be a JavaScript Object that would have property of type and depending on the action that we type we would return a new state. We usually by convention use a SWITCH statement inside our Reducer to organize our actions (little easier than using a if/else statement). In this switch we would do an action.type and our default would return state:

Reducer.js

Reducer will return state or a new state depending on whatever we have with our action. You can also set up a default state/initial state:

Reducer.js

Then Import our Reducer inside our store.js:

Store.js

Now we can to import our store to our index.js and pass it inside the <Provider store={store}> as a PROP:

Index.js

NOW we’re set up with our REDUX!!! And we should be good to go with our store set up!!

Set Up a Component To Render Our Async Fetch Request:

Now that we have all the pre-set-up stuff done, we can go into how to incorporate thunk in our Components to asynchronously fetch our data from our backend by using Redux.

First, Start by building out a Class Component where you’ll be rendering your data onto the page.

I’ll use my Project as an example for this blog:

The App I created is a Dance Reel Builder where professional Dancers and Choreographers can organize all their projects into different fields. We have, Commercial Dance, Concert Dance, and Theater Dance for this example. Right now I’ll walk you through How I grabbed all my data for Commercial Dance from my Rails backend and displayed it onto the page.

Create an Action Creator for your Commercial Dance projects:

How can I make a fetch request to grab all the commercial dance and have them show up on the page??? This is where our asynchronous thunk is going to come in, so first create your Action file — CommercialActions.js. THE way we would/used to build out an action creator for getting all commercial dance is by building out something like a function that takes in all the commercial dance. Then we’d want to return an object that had a type o f “SET_COMMERCIAL” and a payload of all our commercial dance:

CommercialAction.js

This is how we would write this action creator without thunk.

NOW that we have thunk — we can abstract out our fetch logic in here. In my Reducer i’m going to set up a case in the switch statement for SET_COMMERCIAL. If we hit this action type of SET_COMMERCIAL — return new object return state . First we need to spread out our state ```…state```, because we don’t want to lose all our previous state, we have to copy everything that’s in our state. I would only be calling commercial: on first load, there’s nothing inside our array (commercial: [] my initial state) yet and even if we did have something there, this is getting all that data from my backend. If for some reason this got called twice I don’t want to add it on and duplicate my data and keep adding it on to the end (commercial: ). So we just want to reset my Commercials even if I were to call it again I want to reset it to what my backend gives me. We need to write action.payload , BECAUSE it’s the key we sent through ( for type: “SET_COMMERCIAL”, payload: commercial), our payload is our data we’ll be getting back from our backend:

Reducer.js

SO we applied this thunk middleware - WHICH means that now I can make fetch request out of react and move it to redux.

GO TO action creator setCommercial inside my CommercialAction.js . NOW instead of returning this object directly what I’m going to do is return a function that passes in dispatch as an argument, thunk is going to pass in dispatch as an argument by calling this function we’re returning here. THEN inside this function we can make our fetch request, we can do any asynchronous logic or any logic that we want — BECAUSE now it’s a callback:

CommercialAction.js

I can make my fetch request and then take my commercials and call dispatch here in the fetch request because I have access to the dispatch function. What thunk does by allowing me to pass in that callback is gives me access to dispatch within my action creators or within whatever I’m passing to dispatch here. NowI can call dispatch and pass in this action object — type: “SET_COMMERCIAL” and a payload of the data I got from the fetch request payload: commercials:

CommercialAction.js

Remember we can do all of this because I imported that thunk middleware and added to my store here:

Store.js

If I don’t have the last line where I’m passing in thunk i cannot pass dispatch a function I can only pass it objects

NOW we have our action setup here , we want to implement this into my CommercialContainer so I can fetch my commercials and have them show up on the page.

We’ll need mapStateToProps — need to import in “connect” from the react-redux library:

CommercialContainer.js

Connect has to do with connecting the react and redux libraries — connect() is a function that we’re going to call and then it’s going to return another function and then that function expects our Component as it’s arg — so we’re calling what connect() returns with the argument of our CommercialContainer:

Put this at the bottom of your file

We have mapStateToProps and mapDispatchToProps.

We need to create mapStateToProps function that returns an object that will be merged with our PROPS. We then need to pass in our state , we want to map anything to PROPS in our state that we’re going to need in this component. So for us we just need commercial: and we’ll be pulling that out from our state (from store) .commercial

CommercialContainer.js

Think of this more as coming from my store itself and set up our initial state inside of my reducer — this is how my state looks in my store:

So what I’m looking at in my mapStateToProps(stateFromStore) is that my statFromStore is my whole state from my store — and this argument has no idea what container I’m in, if i’m in commercial, or concert, it’s just going to pull in my whole state from my store. Then I can choose here to map all of it to my props — BUT in this case I don’t need all of it so I’ll just pull all my commercial state

NOW let’s get this rendered on the page — So now that I have these in PROPS lets render a p tag with the name of each commercial — map over each commercial and display the name:

CommercialContainer.js

mapDispatchToProps is really just a callback function, so it can take in ‘dispatch’ as an argument — the whole point to matchDispatchToProps, is to get access to this dispatch function. We want to return an object that’s going to be merged with our PROPS — REMEMBERING that we’re mapping this dispatch function to our PROPS :

CommercialContainer.js

THEN here, following convention we’re going to want to use our SET_COMMERCIAL action that we defined in our CommercialAction, SO import it in:

THEN want to write SET_COMMERCIAL as our key inside our return{} WHICH should be a callback function that’s going to be dispatching — we could write our object in there directly like:

BUT instead we’re going to follow the convention, because we have this more reusable action creator that I’m going to call here that we’ve defined setCommercial on. We’re importing a function and calling it inside dispatch, BECAUSE the return value of this function is that object we want. SO we’re still passing dispatch this Object we’re just calling this function to get access to it.

CommercialContainer.js

instead of having this big fetch request inside my componentDidMount() (how we would make our fetch request without thunk) all I need to do is call this function this.props.dispatchSetCommercial() inside my ComponentDidMount:

This is going to fire off this inside my mapDispatchToProps(), dispatch(setCommercial). And then dispatch(setCommercial()) is going to call that function we passed in here which is the function inside our CommercialAction, setCommercial (remember we imported in in at the top of the file). Which passes in dispatch (and a couple other args if we define them) — AND then it’s going to send off this fetch request and then it can dispatch again AND THIS is how we implement asynchronous REDUX!

--

--

--

Software Engineer Student🧚🏼

Love podcasts or audiobooks? Learn on the go with our new app.

JSKongress meets Mozilla SpiderMonkey

Loop in Vue.js(Angular to Vue.js-Part 5)

Set Up Vue.js Environment & Create Vue Instance in 2 Simple Ways

NodeJS Event loop and libuv

A bluffer’s guide to React Router v4

Mastering Full Stack Engineering Work Log

Web App for Docker

Event Delegation in JS

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Milan Page

Milan Page

Software Engineer Student🧚🏼

More from Medium

Contact Picker API In React

Sorting Table Columns

I can’t install react using npx create-react-app. Here’s the solution — Let Me Fail

A Look at the Redux connect() Function