Hey there! You're using an out-of-date browser, so this site probably looks pretty funny. Upgrade your browser for the full experience.

A very basic intro to React redux-saga

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

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.

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
which applies the saga middleware to our redux store so redux actions actually pass through our saga functions.

And last, we have

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:

Born and raised in
Louisville, Kentucky.


223 S. Clay St

Work With Us

  • This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
  • This field is for validation purposes and should be left unchanged.