by Pritish Vaidya

How to monitor network changes using Redux Saga in React Native

9nkd8lAoE4QWGclLuTK3DYa45MdCYXZX34jJ
Image Credit — Unspash

Why should I use Redux Saga to monitor Network Changes?

icYVSeaXDsfe83z7SkYSyKE-AKKWjQF7XOE5
Image Credit — ImgFlip

Redux Saga is an alternate side effect model for redux apps. It is easier to manage, execute, test and catch errors.

Rather than implementing the logic to manage the network state in your react component, the side-effects should be handled separately. Redux Saga provides us with eventChannel as an out of the box solution for handling such cases.

What is an Event Channel?

1OSYcBjFfR0OqQ1JNH20hEvGHZ1Xrbzzv2em
Image Credit — Unsplash

Redux Saga consists of eventChannels to communicate between external events and sagas as a factory function. The events are from the event sources other than the redux store.

Here’s a basic example from the docs:

import { eventChannel } from 'redux-saga'

function countdown(secs) {
  return eventChannel(emitter => {
      const iv = setInterval(() => {
        secs -= 1
        if (secs > 0) {
          emitter(secs)
        } else {
          // this causes the channel to close
          emitter(END)
        }
      }, 1000);
      return () => {
        clearInterval(iv)
      }
    }
  )
}

Things to note:

  • The first argument of the eventChannel is a listener function.
  • The return method is the unregister listener function.

Emitter initializes the listener once after which all the events from the listener are passed to the emitter function by invoking it.

How should I hook up Redux Saga’s Event Channel with React Native’s Network(NetInfo) API?

The React Native’s NetInfo isConnected API asynchronously fetches a boolean which determines whether the device is online or offline.

Dive into the code

1MwK-maPG4EYywcUFOeyEAZTUxleIx8DSSM0
Image Credit — Unsplash

First, we need to create a start channel method.

import { NetInfo } from "react-native"
import { eventChannel} from "redux-saga"

function * startChannel() {
  const channel = eventChannel(listener => {
    const handleConnectivityChange = (isConnected) => {
      listener(isConnected);
    }
    
// Initialise the connectivity listener
    NetInfo.isConnected.addEventListener("connectionChange", handleConnectivityChange);
    
// Return the unregister event listener.
    return () =>
      NetInfo.isConnected.removeEventListener("connectionChange",    handleConnectivityChange);
  });
}

The next step is to listen for the event changes within the channel.

...

while (true) {
  const connectionInfo = yield take(channel);
}

...

The final step is to pass a custom action to the channel so that the value can be synced using your action.

...
function * startChannel(syncActionName) {

...
while (true) {
  const connectionInfo = yield take(channel);
  yield put({type: syncActionName, status: connectionInfo });
}

This channel can be used in our default exported generator by using the call operation.

export default function* netInfoSaga() {
  try {
    yield call(startChannel, 'CONNECTION_STATUS');
  } catch (e) {
    console.log(e);
  }
}

The exported generator can then be imported and used as a detached task using spawn/fork operation in our main saga.

Usage

The above code has added it as a package react-native-network-status-saga to include some of the more useful and cool parameters.

Here are the links

Thanks for reading. If you liked this article, show your support by clapping this article to share with other people on Medium.

More of the cool stuff can be found on my StackOverflow and GitHub profiles.

Follow me on LinkedIn, Medium, Twitter for further update new articles.