How to Easily Manage Connection Status Updates in React Native

When building mobile applications, it‘s critical to gracefully handle scenarios where the user‘s device loses internet connectivity. Without the proper infrastructure in place, your app may appear unresponsive or broken when the user attempts actions that require an active connection. Even worse, the user may have no insight into why the app isn‘t behaving as expected.

As a React Native developer, your goal should be to proactively detect changes between online and offline states so you can keep the user informed and prevent errors from occurring. While it‘s possible to manually check the connection status, this approach quickly becomes tedious and error-prone as your app grows in size and complexity.

Fortunately, React Native provides a simple, yet powerful tool for subscribing to network status changes – the NetInfo module. In this tutorial, we‘ll walk through leveraging NetInfo and React‘s Context API to effortlessly share and update the connection status across your entire React Native application.

React Native NetInfo

The Connectivity Challenge

Before we dive into the code, let‘s examine some of the difficulties you may encounter trying to manage the connection state on your own:

  1. Continuously polling the connection – To accurately reflect the current status, you‘d need to check the connectivity on a frequent interval. This means setting up timers and handling their cleanup to avoid memory leaks.

  2. Passing the status across the component tree – Once you‘ve determined if the app is online or offline, you need a way to provide that information to components that depend on it. With just props, you‘ll quickly find yourself prop drilling through multiple levels.

  3. Triggering UI updates when the status changes – After passing the connection state to a component, you then need to subscribe to changes and force a re-render to update the UI accordingly. This requires careful tracking of event listeners.

As you can imagine, that‘s a lot of complex setup and cleanup code to write and maintain. Luckily, there‘s a better way!

Leveraging the NetInfo Module

The NetInfo module acts as a wrapper around the native connectivity APIs on iOS and Android. It provides a simple interface for both querying the current connection type (e.g. wifi, cellular, none) and subscribing to status changes. Best of all, it handles all the nuances of setup and teardown for you.

Here‘s a quick example of how you can use NetInfo to log whether the device is online or offline:

import NetInfo from "@react-native-community/netinfo";

// Subscribe
const unsubscribe = NetInfo.addEventListener(state => {
  console.log("Connection type", state.type);
  console.log("Is connected?", state.isConnected);
});

// Unsubscribe 
unsubscribe();

Notice how we store the result of calling addEventListener. NetInfo returns an unsubscribe function that removes the listener when called. It‘s a good habit to get into for preventing memory leaks.

Now that we know how to retrieve the connection status, let‘s look at how to share it efficiently across our app.

Creating a Connection Status Provider

Since we want to access the online/offline state from any component, we‘ll use React‘s Context API to create a provider component. If you‘re not familiar with Context, it‘s a way to pass data through the component tree without having to manually thread props down at every level.

Here‘s what our ConnectionStatusProvider will look like:

import React, { createContext, useState, useEffect } from ‘react‘;
import NetInfo from ‘@react-native-community/netinfo‘;

// Create Context object
const ConnectionStatusContext = createContext(null);

const ConnectionStatusProvider = ({ children }) => {
  const [isConnected, setIsConnected] = useState(true);

  useEffect(() => {
    // Subscribe to network state updates
     const unsubscribe = NetInfo.addEventListener(state => {
      setIsConnected(state.isConnected);
    });

    return () => {
      // Unsubscribe to network state updates
      unsubscribe();
    };
  }, []);

  return (
    <ConnectionStatusContext.Provider value={isConnected}>
      {children}
    </ConnectionStatusContext.Provider>
  );
};

export default ConnectionStatusProvider;

export function useConnectionStatus() {
  const context = useContext(ConnectionStatusContext);
  if (context === null) {
    throw new Error(‘useConnectionStatus must be used within a ConnectionStatusProvider‘);
  }
  return context;
}

Let‘s break this down:

  1. We create a new Context object to hold our connection status
  2. In the provider component, we initialize state to track the status
  3. Inside a useEffect hook, we subscribe to NetInfo changes and update the state
  4. The provider wraps its children with the Context Provider and sets the value to the current status
  5. We create a custom useConnectionStatus hook to easily consume the value in child components

With our provider ready, the final step is to wrap our app with it.

Providing the Connection Status

At the top-level of your app, import the ConnectionStatusProvider and use it to wrap your other components:

import React from ‘react‘;
import { View } from ‘react-native‘;
import ConnectionStatusProvider from ‘./ConnectionStatusProvider‘;

const App = () => {
  return (
    <ConnectionStatusProvider>
      <View>
        {/* Other components */}
      </View>
    </ConnectionStatusProvider>
  );
};

export default App;

That‘s it! We can now access the connection status from any child component like so:

import React from ‘react‘;
import { Text } from ‘react-native‘;
import { useConnectionStatus } from ‘./ConnectionStatusProvider‘;

const MyComponent = () => {
  const isConnected = useConnectionStatus();

  return (
    <Text>
      {isConnected ? ‘Online‘ : ‘Offline‘}  
    </Text>
  );
};

export default MyComponent;

The useConnectionStatus hook allows us to inline the status in our render method for easy conditionals. You can use this to display banners, disable buttons, or fetch data depending on the state.

Comparing Context to Redux

You might be wondering – could we have used a state management library like Redux to achieve the same result? Absolutely! The reason I prefer Context for this scenario is that it‘s a perfect fit for sharing simple, global state.

Using Redux would add a bunch of extra concepts and boilerplate:

  • Actions to update the status
  • A reducer to handle those actions
  • A selector to retrieve the status
  • Wiring up the component with connect()

Unless you‘re already using Redux and are very comfortable with it, I find Context to be a lighter and more straightforward solution for this particular problem. It keeps our dependency list small and lets us take advantage of modern React features like hooks.

Conclusion

And there you have it! With just a bit of setup, we now have an easy and reliable way to keep tabs on our app‘s connection status. More importantly, we can use that knowledge to craft a better user experience by adjusting our app‘s behavior when the user goes offline.

The beauty of this pattern is that it‘s not limited to network state. You can follow the same steps to share any type of global data, such as:

  • User authentication status
  • Theme settings (light vs dark mode)
  • Localization preferences

By taking advantage of React‘s built-in tools, we can minimize complexity and keep our codebase lean and maintainable. The Context API is a powerful ally in the battle against prop drilling and is quickly becoming my go-to for these types of scenarios.

So the next time you need to share state but aren‘t sure if it‘s worth pulling in Redux, give Context a shot! I think you‘ll find it‘s a nice middle ground.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *