Handling Download Progress with Redux Saga

You probably know how to use methods returning promises in a Redux-Saga but have you ever wondered what to do in case you need to track progress?

Recently I have started a React Native project in which I setup my now usual stack for managing app state, Redux + Redux-Saga. Everything was going well until I installed the React Native Fetch Blob in order to be able to download files in my app.

The fetch method returns what they call a StatefulPromise containing the following:

cancel():Promise

progress(config, (received, total) => void)

then((result) => void)

catch((error) => void)

If you are used to the call method, you probably know by now that it can only handle a regular promise. But here we also want to handle progress and to be able to cancel the download.

This is where Saga’s eventChannel comes into play. As you will see, eventChannel will allow you to setup regular functions with multiple callbacks to be used in sagas. The first step is to take the fetch method and wrap it in a Saga helper.

A small drawback is that if the progress event is fired too often it will trigger too many dispatches and renders which in turn will freeze access to your store (and subsenquently your app). This is why we used the { interval: 200 } progress option to limit calls.

If the library you use doesn’t offer this option you can still use a throttler such as lodash’s directly on the callback. Our progress method then ressembles this: