Redux-Saga tutorial for beginners and dog lovers
By: Ryan J. Yost
Tags: Redux Saga, JavaScript, Web Development, React, Redux

Redux-Saga tutorial for beginners and dog lovers

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 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.

What you’ll build

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.

Let’s get started

Create a new app with 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-saga

npm 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.

Like this tutorial?

Get more by subscribing to the Yost’s Posts newsletter.

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

API_CALL_REQUEST says that we’re beginning the process of fetching a dog from the Dog API.

says that we’re beginning the process of a dog from the Dog API. API_CALL_SUCCESS tells the Store that we successfully retrieved a dog and are therefore no longer in the process of fetching one.

tells the Store that we successfully retrieved a and are therefore no longer in the process of one. API_CALL_FAILURE tells the Store that something went wrong with our API call. We received an error rather than a new dog .

But how should we make the API_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.

If successful, we’ll get a new dog and dispatch API_CALL_SUCCESS along with the dog .

and dispatch along with the . If a failure, we’ll get an error and dispatch API_CALL_FAILURE along with the error .

Install redux-saga .

npm install --save redux-saga

Also install axios , which will help us make 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 .

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 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

Now let’s walk through sagas.js

a watcherSaga is a saga that watches for an action to be dispatched to the Store, triggering a workerSaga .

is a saga that watches for an action to be dispatched to the Store, triggering a . takeLatest is a helper function provided by redux-saga that will trigger a new workerSaga when it sees an API_CALL_REQUEST , while cancelling any previously triggered workerSaga still in process.

is a helper function provided by that will trigger a new when it sees an , while cancelling any previously triggered still in process. fetchDog simply uses axios to request a random dog image from the Dog API and returns a Promise for the response.

simply uses to request a random dog image from the Dog API and returns a for the response. workerSaga attempts to fetchDog , using another redux-saga helper function call , and stores the result (a resolved or failed Promise ) in a response variable.

attempts to , using another helper function , and stores the result (a resolved or failed ) in a variable. If fetchDog was a success, we extract the dog image from the response and dispatch an API_CALL_SUCCESS action with dog in the payload to the Store, using ANOTHER redux-saga helper function put .

was a success, we extract the image from the and dispatch an action with in the payload to the Store, using ANOTHER helper function . If there was an error with fetchDog , we let the Store know about it by dispatching an API_CALL_FAILURE action with the error .

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 .

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.

createStore with our reducer

with our Connect the Redux DevTools to the Store for debugging and learning

And wrap the <App/> component in a <Provider/> component with the store , which let’s us work with Redux in React.

component in a component with the , which let’s us work with Redux in React. We’ll actually connect() the <App/> component shortly.

To make our redux-saga work with Redux…

createSagaMiddleware , and apply it to the Redux store with some help from compose and applyMiddleware

, and apply it to the Redux with some help from and run the watcherSaga , so that it can trigger the workerSaga when there’s an API_CALL_REQUEST

Connect <App /> to Redux

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