PHP, Javascript & React + Frontend Development

A very basic intro to React redux-saga

By:

Mark Biek

on 1/14/2019

Today, we’re going to do a very brief introduction to Redux-Saga and why it makes React+Redux apps much easier.

To save space, we’ll only be showing the important bits of our app code. Complete, working versions of the app are available on Github:
Basic React+Redux Code
Redux-Saga Code

A Basic App

To see what kinds of problems Redux-Saga helps solve, let’s make a small application that doesn’t use it!

We’ll use a USGS data feed to show a simple list of recent earthquakes.

Here’s our main App component:

There isn’t anything too weird going on here.

When our component mounts, we make an ajax call to get the data we want. Then that data is dispatched to the Redux store.

Once the store is populated, we display our list.

For a simple example, this is totally fine. For a larger application, however, you can see how this structure isn’t going to scale very well.

If we have lots of ajax calls to make, or we have calls that are dependent on each other, the above approach is going to get ugly in a hurry.

Making it better

The basic idea behind Redux-Saga is that it acts as a separate thread for your application. All of your application side-effects (like ajax calls) go in this thread instead of being called from your components.

You can also watch for certain redux actions use those to trigger other actions.

Behind the scenes, Redux-Saga is using ES6 Generators.These are a powerful programming tool and definitely worth learning, but that’s too much to go into here.

Now let’s update our simple app to use Redux-Saga!

Step 1: Updating the redux store

The first step is updating the redux store to use the saga middleware.

There are a couple of oddities here.

First we have
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

We need that so our app will still work with the Redux Dev Tools extension

The next part is
composeEnhancers(applyMiddleware(sagaMiddleware))
which applies the saga middleware to our redux store so redux actions actually pass through our saga functions.

And last, we have
sagaMiddleware.run(handleLoadQuakes);
sagaMiddleware.run(rootSaga);

The handleLoadQuakes function contains the code that was previously in the componentDidMount of our App component. The sagaMiddlware.run(handleLoadQuakes) calls that function to do our initial data load.

The second call runs our root saga which will be responsible for watching for any redux actions we’re interested in.

Step 2: Load some data

Let’s take a look at handleLoadQuakes. As we mentioned before, this will run once when our app first loads.

Notice the * here?
export function* handleLoadQuakes() {

That means that handleLoadQuakes is a generator function. Almost every saga function you write is going to be defined that way.

The next thing you’ll notice is that we moved our ajax call to a separate (non-generator) function called fetchQuakes. This function just makes the ajax call and returns the promise from it.

That’s so we can call fetchQuakes like this
let resp = yield call(fetchQuakes);

The call is one of the Redux-Saga helper functions. It essentially behaves like calling a function using async-await. Our handleLoadQuakes will wait until the ajax call finishes before continuing on.

Last but not least, we dispatch a new redux action when the ajax call is complete
yield put({ type: 'SET_QUAKES', quakes: resp.data.features, });

One nice thing about the saga approach is it makes it super easy to do loading/error states by updating our handleLoadQuakes to something like this

Step 3: Watch for some actions

The first part of watching for redux actions is setting up our root saga (the one that we called back up in the redux store).

We define saga functions for any redux actions we want to watch for, then include them in the root saga and the saga middleware takes care of the rest.

In our case, we just have the one function watchRefreshQuakes which looks like

The magic here is the takeEvery function. This will listen for every REFRESH_QUAKES redux action that comes through.

The best part is, when a REFRESH_QUAKES action is received, we turn around and call the very same handleLoadQuakes function we defined previously!

Step 4: The sky is the limit!

Now that we’ve walked through the basics, here are some additional steps you can take:

Share to

Related Posts

Wordpress to Sanity Data Script

By:Nick Stewart on 3/11/2021

One of the biggest challenges of moving from one CMS to another is getting your existing data to the new platform. In our case, we were moving our existing WordPress platform, which had been around for years, over to the Sanity.io platform.

Read More »
Developing the New via.studio

By:Alec Robertson on 6/14/2021

A deep dive into creating a fast, user-focused experience on the latest web technology stack for the new via.studio website.

Read More »