Build a simple app that fetches dog images using React, Redux & Redux-Saga

Michael Gil — https://www.flickr.com/photos/msvg/

I began using [redux-saga](https://redux-saga.js.org/) at work in a fairly complex boilerplate.

The path to becoming even a little bit comfortable with it was winding and suboptimal, so I thought I’d write the tutorial I wish I’d had when just starting out with sagas.

This tutorial assumes you have a solid grasp of React or React Native and Redux. If you’re not ready for redux-saga (yet), I’d definitely recommend that you check out this amazing, MASSIVE treasure trove of resources for learning React and Redux.

markerikson/react-redux-links_react-redux-links — Curated tutorial and resource links I’ve collected on React, Redux, ES6, and more_github.com

What you’ll build

Dog Saga - Redux-Saga Beginner Tutorial_Super simple app for a beginner redux-saga tutorial._ryanjyost.github.io

What’s redux-saga? Why would I want or need it?

From the official repo:

redux-saga is a library that aims to make application side effects (i.e. asynchronous things like data fetching and impure things like accessing the browser cache) easier to manage, more efficient to execute, simple to test, and better at handling failures.

I think of it as an organized way of helping your Redux app communicate and stay in-sync with the outside world — mainly external APIs.

Many wonderful people have opined on the pros, cons, and everything else about redux-saga, much better than I could — so here are some links if you want to really nail down the WHATs and WHYs.

We’ll be focusing on the HOW.

Read Me · Redux-Saga_The mental model is that a saga is like a separate thread in your application that's solely responsible for side…_redux-saga.js.org

Managing Side Effects In React + Redux Using Sagas_For me, there has always been one thorn in the React+Flux setup, which is that more complicated processes involving…_jaysoo.ca

Redux Saga: The Future is 1975_WTF is a clock? (This is the first post in a three-part introduction to Redux Saga. The second post is here, and the…_ohyayanotherblog.ghost.io

Using redux-saga To Simplify Your Growing React Native Codebase_Some of the most fragile, embarrassing, and unreadable code you will write is flow control. — Beowulf_shift.infinite.red

What is Redux-Saga?_Redux-saga is a redux middleware library, that is designed to make handling side effects in your redux app nice and…_engineering.universe.com

Redux nowadays : From actions creators to sagas_There's this expression I say each time I stumble on something (some technology) that's going to change my habits in…_riad.blog

Master Complex Redux Workflows with Sagas_Learn how to handle intricate procedures with async watcher routines (sagas) that monitor your Redux events. Brandon…_konkle.us

Let’s get started

Create a new app with [create-react-app](https://github.com/facebookincubator/create-react-app).

npx create-react-app dog-saga

Confused by the npx? So was I, until I read this.

Enter the project’s directory and fire up the app.

cd dog-saganpm start

You should now see the boilerplate for create-react-app, with it’s spinning React logo. You’ll be replacing it with cute dogs soon enough.

Redux

Install redux.

npm install --save redux

Create a new file in your src folder called redux.js and add the following code to it.

We have three action types and a single reducer

But how should we make theAPI_CALL_REQUEST?

How does the Store know whether the API call was a success or a failure?

HOW DO WE GET PICTURES OF CUTE DOGS DAMNIT??? With a saga.

P.S. We’re not gonna use action creators in this app. For something so simple, they may muddy the waters. Also, you’ll see how redux-saga handles and dispatches actions more clearly (in my opinion) without them.

Redux-Saga

We want to create a saga, using redux-saga, that will initiate an API call for a dog image, then tell the Store whether that API call was a success or a failure.

Install redux-saga.

npm install --save redux-saga

Also install [axios](https://github.com/axios/axios), which will help us make [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)-based API calls.

npm install axios

Create a new file called sagas.js and add the following code to it.

Before we walk through this new file, notice the function* syntax. This creates a special kind of function new to ES6 called a [generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*).

Generators can pause and restart — be exited and re-entered — and actually remember the context/state of the function over time.

Each yield in a generator basically represents an asynchronous step in a more synchronous/sequential process — somewhat like await in an [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) function.

redux-saga relies on generators, but does a decent amount of the work for us, so (in my fairly limited experience) a deep understanding of them for this use-case isn’t necessary.

Here are some resources if you want to learn more about generators

The Basics Of ES6 Generators_ES6 Generators: Complete Series The Basics Of ES6 Generators Diving Deeper With ES6 Generators Going Async With ES6…_davidwalsh.name

The Hidden Power of ES6 Generators: Observable Async Flow Control_In 7 Surprising Things I Learned Writing a Fibonacci Generator in JavaScript, I covered one obvious use-case for ES6…_medium.com

Now let’s walk through **sagas.js**

Phew! It’s a little weird at the beginning, but this pattern/procedure and its benefits become more clear after a few implementations.

Hook up React, Redux and Redux-Saga

Ok, we have our pieces, now it’s time to put them all together.

Install [react-redux](https://github.com/reactjs/react-redux).

npm install --save react-redux

Also, install Redux Devtools — must-have for debugging and seeing Redux (and sagas’ related actions) in action. Go here for info on setting up the Redux dev tools. I recommend using the browser extension.

Open your index.js file and make it look like the file below.

The Redux stuff should look familiar.

To make our redux-saga work with Redux…

Connect <App /> to Redux

Open up App.js and paste the following code into it.

Bring it all together on the screen

Now let’s walk through some of the changes (top to bottom) made to the App component’s rendered output, which allow the user to see the current state of the app and request dog images.

All of these snippets are from the **App.js** above, so no new code here.

In the snippet below, we tweaked the image src to show a dog image if one exists in the Store. If dog is null, it falls back to the React logo.

If the current state of our app has a dog image, we tell the user to keep clicking. If not, we tell them to replace the React logo with a dog.

If the current state has an error, we display some text to let the user know.

Here, if our sagas are currently in the process of fetching a new dog image, which means workerSaga has not dispatched an API_CALL_SUCCESS or API_CALL_FAILURE yet, we disable the button.

Otherwise, we provide a button for the user to click and request a random dog image.

Just for fun, let’s cause an error

To see the workerSaga dispatch an API_CALL_FAILURE, go into sagas.js and mess up the url for the dog api (like changing “breeds” to “beds”).

Now when you click the “Request a Dog” button, the error message displays!

A recap, step-by-step

  1. An event takes place — e.g. user does something (clicks “Request a Dog” button) or an update occurs (like componentDidMount)
  2. Based on the event, an action is dispatched, likely through a function declared in mapDispatchToProps (e.g.onRequestDog)
  3. A watcherSaga sees the action and triggers a workerSaga. Use saga helpers to watch for actions differently.
  4. While the saga is starting, the action also hits a reducer and updates some piece of state to indicate that the saga has begun and is in process (e.g. fetching).
  5. The workerSaga performs some side-effect operation (e.g. fetchDog).
  6. Based on the result of the workerSaga‘s operation, it dispatches an action to indicate that result. If successful (API_CALL_SUCCESS), you might include a payload in the action (e.g. dog). If an error (API_CALL_FAILURE), you might send along an error object for more details on what went wrong.
  7. The reducer handles the success or failure action from the workerSaga and updates the Store accordingly with any new data, as well as sets the “in process” indicator (e.g. fetching) to false.

Throughout this process, you can use the updates to Redux state flowing through to props to keep your user informed of the process and progress thereof.

More resources

Async operations using redux-saga_UPDATE August/2017:_medium.freecodecamp.org

This collection of common Redux-saga patterns will make your life easier._This is a 2-part series — feel free to check out the first part here._medium.freecodecamp.org