Asynchronous cat fetching with Redux-Saga

William Hitchcock
3 min readAug 27, 2019

--

In this article we’ll go over setting up a simple web app that will handle asynchronously fetching data from a public api using redux saga (we’ll use https://thecatapi.com/). By the end of this walk though you should have an understanding of how to handle asynchronous actions using redux-saga. We will build an app that fetches a random cat image.

Feel free to use this article as a reference for setting up new projects using redux-saga!

0. Create a React app (if you don’t already have one)

If you don’t already have a react app it’s really easy to create one (for more info on create-react-app see https://github.com/facebook/create-react-app):

If you’re integrating redux saga into your own project, feel free to skip this step, or use a different view library all together!

npx create-react-app my-app && cd my-app

1. Install dependencies

You’ll need the following additional packages:

  • redux
  • redux-saga
  • reselect (optional, feel free to use a different selector strategy)
  • react-redux (optional, if you’re not using react you’ll need a different connector)
  • axios (optional, we’re going to use axios for making our http requests, but feel free to use something else)
npm install --save redux redux-saga reselect axios

2. Actions (and action creators)

I personally prefer to declare my action types as consts in a dedicated const.js file:

…and the action creators, we’ll use these later to describe events that occur within our app:

3. Reducer(s)

Our reducer will receive every action that is dispatched and its job is to return a new state. Apps can have multiple reducers that are typically responsible for an individual part of state (commonly referred to as slices). For our app we’ll just have one reducer that will handle the three action types we declared:

4. Saga(s)

Our saga will describe the asynchronous workflow that needs to be performed in response to our FETCH_CAT action. Then we will dispatch new actions based on the outcome of our execution. A few notes on the redux-saga api (complete documentation can be found here: https://redux-saga.js.org/):

  • takeLatest will run the associated generator function for only the latest dispatched FETCH_CAT
  • call is pretty much what it sounds like, it calls the function specified by the first argument ( axios.get in our case ) with the parameters in the next argument which is an array. This basically allows us to use our promise with yield.
  • put is similar to call but it calls Redux'sdispatch function.

What is nice about this is that it is a fairly readable representation of our asynchronous logic without the nesting required by promises.

  1. We call the api at the url for the api store the response in our variable response when it is completed
  2. Once the response is received we dispatch a new action describing the event (we got a response from the api)
  3. If there is an error (line 9 will throw an error if the api responds with an error) we dispatch an new action describing that event (there was an error fetching the cat)

5. Plumbing

Now we need to make sure that our reducers and sagas are added to our redux store. This is just a bit of plumbing to make sure that redux’s dispatch function.

  1. We create a root saga, just named saga that yields all of our exported sagas, basically just runs all of our generators so they are ready to receive actions.
  2. We set up our redux store as normal with our combined reducers.
  3. We call create store and export the resulting store as default so it can be used in our application.
  4. Finally we instruct the saga middleware to run saga

6. View layer

Now our view layer will look pretty much like any normal react-redux container. We map dispatch and any selectors we need to our component and then use them in the component.

Thats it, now you have a functioning app that asynchronously fetches random cat images.

--

--