Search code examples
reactjstypescriptreact-nativenetwork-connection

Why is React Native's NetInfo not being triggered properly when starting app w/o Internet?


I have a component to track the Internet connectivity of the device and display a small red banner when there is no connection. In general, it works properly: when you are in the app and you toggle your Internet, the banner appears and disappears.

However, if you start the app with no Internet, it does not show the banner. Once you turn Internet on, it will from then on will work properly.


Here is the component, OfflineNotice.tsx:

import * as React from 'react';
import { NetInfo, StyleSheet, Text, View } from 'react-native';

interface State {
  isConnected: boolean;
}

export class OfflineNotice extends React.Component<any, State> {
  public state = {
    isConnected: true,
  };

  public handleConnectivityChange = (isConnected: boolean) => {
    if (isConnected !== this.state.isConnected) {
      console.log('isConnected', isConnected);
      this.setState({ isConnected });
    }
  };

  public componentDidMount() {
    NetInfo.isConnected.addEventListener(
      'connectionChange',
      this.handleConnectivityChange
    );
  }

  public componentWillUnmount() {
    NetInfo.isConnected.removeEventListener(
      'connectionChange',
      this.handleConnectivityChange
    );
  }

  public render() {
    if (!this.state.isConnected) {
      return (
        <View style={styles.container}>
          <Text style={styles.offlineText}>
            No Internet Connection
          </Text>
        </View>
      );
    }
    return null;
  }
}

Solution

  • As JRK pointed out so quickly in his comment above, the solution is simple. Connection changes trigger the event, and when you start the app without Internet, there is no connection change.

    If you initialise isConnected in state as false, the event will be fired when the connection is initiated.

    The best way to do this is in the constructor:

    constructor(props) {
      super(props);
    
      NetInfo.isConnected.fetch().then(isConnected => {
        this.setState({isConnected});
      });
    }
    

    If you don't do this, but instead only set isConnected to false in this.state and add the event listener in componentDidMount, it will not work properly on Android. Props for the above to Terry Bazi from a comment to a Medium article on this subject.

    You can learn more in the examples in the React Native docs on NetInfo, especially the final section on the isConnected property: https://facebook.github.io/react-native/docs/netinfo#properties-1