redux-saga factories and decorators

Tomáš Ehrlich
Jun 13, 2017 · 3 min read

redux-saga is so far the best library for managing asynchronous workflow in redux. I started using simple redux-promise, then moved to redux-thunk only to finally settle with redux-saga. In few cases, it leads to a bit more complicated code than using redux-promise directly in Component, but in overall it makes the code more predictable. Also, readability counts™!

Factories

The first thing I noticed after few days of using redux-saga is that some parts of sagas are very similar to each other. Fetch data from API, catch an error, dispatch successful action with data if everything is ok or dispatch error when something fails. The only thing that’s different is API call and action.

Let’s write a simple factory which returns our saga:

The entity has two actions: request and response. entity.request is dispatched from Component and contains parameters of fetch request in the payload (e.g. object ID, any filters, search, etc.)

api is a function which receives parameters from the entity.request action and performs the API call:

The core of our saga lives inside fetchSaga and can be easily tested and reused. Less code, fewer bugs, but we can go even one step further.

Use case: network failures

Imagine we have several sagas which fetch our data. Now we want to add new functionality to our fetch workflow — that’s very simple, we just need to extend fetchSaga.

So, let’s suppose we want to detect when the network is down and resume our saga when the network is up again. All we need is one simple saga and add few lines to fetchSaga:

networkAction are defined in a different module which handles network status and periodically pings server if it’s back again (it’s a pretty cool example of a complex workflow in redux-saga, so check it out).

reloadEntity waits until the network is up again and then triggers request again which triggers the whole fetchSaga with original parameters. I’m not sure if it’s safe to use it for unsafe requests like POST, DELETE, but for simple GET requests it works great.

Decorators

Factories are functions which returns configured sagas. Sometimes we already have a saga, but we still need to change its behaviour — that’s when decorators are useful.

Use case: authentication

Suppose we have some API endpoints which requires a user to be authenticated. There’re dozens of places where we can check if a user is authenticated or not, but we can also do it centrally in sagas. All that we want is decorate our sagas with authRequired decorator:

Now we can add a simple check that user is authenticated at the beginning of our sagas:

const createProject = authRequired(sendSaga(createProject, apiCreateProject))

where sendSaga is similar factory to fetchSaga, just made for POST requests.

Obviously, we still need the same validation in our backend, but now our users are at least redirected to login page when they try to perform such action.

Composition

Sagas are great that can be composed together. All these little pieces can be written and tested separately and then combined together into the final saga.

Also, if you aren’t still sold to redux-saga, take a look at the example of handling network failure. I guess this would be still possible with redux-thunk, but test such a saga would be really painful.

What’s your favourite factory or decorator?

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade