17 thoughts on “iOS: NetInfo.isConnected returns always false

  1. I’ve reported the same issue before: #8469

    Quick workaround is to add an event handler NetInfo.isConnected.addEventListener('change', Function.prototype)

  2. I solved it this way:

    componentDidMount() {
      const dispatchConnected = isConnected => this.props.dispatch(setIsConnected(isConnected));
    
      NetInfo.isConnected.fetch().then().done(() => {
        NetInfo.isConnected.addEventListener('change', dispatchConnected);
      });
    }
  3. the same issue to me, I am using RN@0.30.0 and the fetch always return unknown.

    But we can use addEventListener instead.

    NetInfo.addEventListener('change',
        (networkType)=> {
            this.setState({networkType})
        }
    )
    

    instead of:

    NetInfo.fetch().done(
        (networkType)=> {
            this.setState({networkType})
        }
    )
    
  4. @florentsorel so in my project I use redux for state management and setIsConnected is my action creator, which looks something like:

    actions/network.js

    export const setIsConnected = (isConnected) => ({
      type: 'SET_IS_CONNECTED',
      isConnected
    });

    and then I have a network reducer:

    reducers/network.js

    const initialState = {
      isConnected: true
    };
    
    const network = (state = initialState, action) => {
      switch (action.type) {
        case 'SET_IS_CONNECTED':
          return {
            isConnected: action.isConnected
          };
    
        default:
          return state;
      }
    }
    
    export default network;
  5. The underlying code hasn’t really changed so I would be surprised if this is “fixed”.

    I put fix in quotes because it seems like the motivation for this change is to only set up the native machinery that watches the network status if the application code is interested in observing it.

    Apps register interest by adding an event listener which then starts checking reachability.

    At this point it seems like this is the desired behaviour so perhaps a documentation change is required. NetInfo.isConnected returns a boolean so it doesn’t express that the state is unknown and that that won’t change until you add an event listener. Alternatively the function could be changed to return null or a boolean.

    My apps have code that is very similar to what @knowbody posted. I don’t call NetInfo.isConnected.fetch() at all, however, as it’s useless at startup.

    i assume there is connectivity, add the listener, and then the state will be updated when the connectivity state is no longer unknown.

  6. RN 0.54.2
    OS: iOS
    same issue, always unknown

    When I Upgrade RN to 0.55.3

    I’m use this code, first return unknown, And then it works

        NetInfo.getConnectionInfo()
            .then()
            .done(() => {
                    switch (connectionInfo.type) {
                        case 'none':
                            Alert.alert('aa', 'none');
                            break;
                        case 'wifi':
                            Alert.alert('aa', 'wifi');
                            break;
                        case 'cellular':
                            if (connectionInfo.effectiveType !== 'unknown') {
                                Alert.alert('aa', `cellular ${connectionInfo.effectiveType}`);
                            } else {
                                Alert.alert('aa', 'cellular unknown');
                            }
                            break;
                        case 'unknown':
                            Alert.alert('aa', 'unknown');
                            break;
                        default:
                            Alert.alert('aa', 'default');
                            break;
                    }
                });
            });
    

    Ok, so let’s do a little trick.

        NetInfo.getConnectionInfo()
            .then()
            .done(() => {
                NetInfo.getConnectionInfo().then(connectionInfo => {
                    switch (connectionInfo.type) {
                        case 'none':
                            Alert.alert('aa', 'none');
                            break;
                        case 'wifi':
                            Alert.alert('aa', 'wifi');
                            break;
                        case 'cellular':
                            if (connectionInfo.effectiveType !== 'unknown') {
                                Alert.alert('aa', `cellular ${connectionInfo.effectiveType}`);
                            } else {
                                Alert.alert('aa', 'cellular unknown');
                            }
                            break;
                        case 'unknown':
                            Alert.alert('aa', 'unknown');
                            break;
                        default:
                            Alert.alert('aa', 'default');
                            break;
                    }
                });
            });
    

    This my solution. Expect an official solution.

  7. Upgraded to 55 specifically because the changelog said it’s supposed to fix this — still broken (0.55.3).

    I am able to get it to work using a similar solution to @yuyao110120:

    NetInfo.isConnected.fetch().then(() => {
      NetInfo.isConnected.fetch().then(isConnected =>
        // isConnected is now the correct value
      });
    });
  8. I no longer trust NetInfo (react-native 0.53.3)
    This is what I do to make sure there’s internet:

    async function handleConnectivityChange(status) {
      const { type } = status;
      let probablyHasInternet;
      try {
        const googleCall = await fetch(
            'https://google.com', {
            headers: {
              'Cache-Control': 'no-cache, no-store, must-revalidate',
              Pragma: 'no-cache',
              Expires: 0,
            },
          });
        probablyHasInternet = googleCall.status === 200;
      } catch (e) {
        probablyHasInternet = false;
      }
    
      console.log(`@@ isConnected: ${probablyHasInternet}`);
    
    }
    
      NetInfo.getConnectionInfo().then(handleConnectivityChange);
      NetInfo.addEventListener('connectionChange', handleConnectivityChange);
  9. @SudoPlz I noticed that fetch caches the request on Android. You’d have to give it some headers to prevent that.

          const googleRequest = await fetch('https://www.google.com', {
            headers: {
              'Cache-Control': 'no-cache, no-store, must-revalidate',
              'Pragma': 'no-cache',
              'Expires': 0
            }
          });
    
  10. Adding an initial connection event listener will cause NetInfo.getConnectionInfo() and NetInfo.isConnected.fetch() to work properly on the first call.

    const onInitialNetConnection = isConnected => {
        console.log(`Is initially connected: ${isConnected}`);
    
        NetInfo.isConnected.removeEventListener(
            onInitialNetConnection
        );
    };
    
    NetInfo.isConnected.addEventListener(
        'connectionChange',
        onInitialNetConnection
    );
    
    // both now work on the first call.
    await NetInfo.getConnectionInfo();
    await NetInfo.isConnected.fetch();
    

    Thanks #8469

    Make sure to import this file or else it will not execute.

    P.S. If you are using fetch, use method: 'HEAD' to reduce the amount of data transmitted.

  11. @octopitus , @martinentelect
    this is my code, I am using react native version 0.55.4, and its a sensible and working workaround until NetInfo is fixed.
    In my api.js file I have this code

    import { NetInfo } from 'react-native';
    import { url } from '[AppName]/src/config';
    
    export const onInitialNetConnection = () => {
        NetInfo.isConnected.removeEventListener(onInitialNetConnection);
    };
    
    const getDataById = async (dataId) => {
        // both now work on the first call.
        await NetInfo.getConnectionInfo();
        const isConnected = await NetInfo.isConnected.fetch();
        if (!isConnected) {
            throw new Error('networkError');
        }
        const response = await fetch(`${url}${dataId}`, {
            headers: {
                'Cache-Control': 'no-cache, no-store, must-revalidate',
                Pragma: 'no-cache',
                Expires: 0,
            },
        });
        if (response.ok) {
            return response.json();
        }
        throw new Error('invalidCode');
    };
    
    export default getDataById;
    

    In my App.js file (my entry point to the application) I add the event listener:

    NetInfo.isConnected.addEventListener(
                'connectionChange',
                onInitialNetConnection,
            );
    

Comments are closed.

11 thoughts on “iOS: NetInfo.isConnected returns always false

  1. I’ve reported the same issue before: #8469

    Quick workaround is to add an event handler NetInfo.isConnected.addEventListener('change', Function.prototype)

  2. I solved it this way:

    componentDidMount() {
      const dispatchConnected = isConnected => this.props.dispatch(setIsConnected(isConnected));
    
      NetInfo.isConnected.fetch().then().done(() => {
        NetInfo.isConnected.addEventListener('change', dispatchConnected);
      });
    }
  3. the same issue to me, I am using RN@0.30.0 and the fetch always return unknown.

    But we can use addEventListener instead.

    NetInfo.addEventListener('change',
        (networkType)=> {
            this.setState({networkType})
        }
    )
    

    instead of:

    NetInfo.fetch().done(
        (networkType)=> {
            this.setState({networkType})
        }
    )
    
  4. @florentsorel so in my project I use redux for state management and setIsConnected is my action creator, which looks something like:

    actions/network.js

    export const setIsConnected = (isConnected) => ({
      type: 'SET_IS_CONNECTED',
      isConnected
    });

    and then I have a network reducer:

    reducers/network.js

    const initialState = {
      isConnected: true
    };
    
    const network = (state = initialState, action) => {
      switch (action.type) {
        case 'SET_IS_CONNECTED':
          return {
            isConnected: action.isConnected
          };
    
        default:
          return state;
      }
    }
    
    export default network;
  5. The underlying code hasn’t really changed so I would be surprised if this is “fixed”.

    I put fix in quotes because it seems like the motivation for this change is to only set up the native machinery that watches the network status if the application code is interested in observing it.

    Apps register interest by adding an event listener which then starts checking reachability.

    At this point it seems like this is the desired behaviour so perhaps a documentation change is required. NetInfo.isConnected returns a boolean so it doesn’t express that the state is unknown and that that won’t change until you add an event listener. Alternatively the function could be changed to return null or a boolean.

    My apps have code that is very similar to what @knowbody posted. I don’t call NetInfo.isConnected.fetch() at all, however, as it’s useless at startup.

    i assume there is connectivity, add the listener, and then the state will be updated when the connectivity state is no longer unknown.

  6. I no longer trust NetInfo (react-native 0.53.3)
    This is what I do to make sure there’s internet:

    async function handleConnectivityChange(status) {
      const { type } = status;
      let probablyHasInternet;
      try {
        const googleCall = await fetch(
            'https://google.com', {
            headers: {
              'Cache-Control': 'no-cache, no-store, must-revalidate',
              Pragma: 'no-cache',
              Expires: 0,
            },
          });
        probablyHasInternet = googleCall.status === 200;
      } catch (e) {
        probablyHasInternet = false;
      }
    
      console.log(`@@ isConnected: ${probablyHasInternet}`);
    
    }
    
      NetInfo.getConnectionInfo().then(handleConnectivityChange);
      NetInfo.addEventListener('connectionChange', handleConnectivityChange);
  7. Adding an initial connection event listener will cause NetInfo.getConnectionInfo() and NetInfo.isConnected.fetch() to work properly on the first call.

    const onInitialNetConnection = isConnected => {
        console.log(`Is initially connected: ${isConnected}`);
    
        NetInfo.isConnected.removeEventListener(
            onInitialNetConnection
        );
    };
    
    NetInfo.isConnected.addEventListener(
        'connectionChange',
        onInitialNetConnection
    );
    
    // both now work on the first call.
    await NetInfo.getConnectionInfo();
    await NetInfo.isConnected.fetch();
    

    Thanks #8469

    Make sure to import this file or else it will not execute.

    P.S. If you are using fetch, use method: 'HEAD' to reduce the amount of data transmitted.

  8. @octopitus , @martinentelect
    this is my code, I am using react native version 0.55.4, and its a sensible and working workaround until NetInfo is fixed.
    In my api.js file I have this code

    import { NetInfo } from 'react-native';
    import { url } from '[AppName]/src/config';
    
    export const onInitialNetConnection = () => {
        NetInfo.isConnected.removeEventListener(onInitialNetConnection);
    };
    
    const getDataById = async (dataId) => {
        // both now work on the first call.
        await NetInfo.getConnectionInfo();
        const isConnected = await NetInfo.isConnected.fetch();
        if (!isConnected) {
            throw new Error('networkError');
        }
        const response = await fetch(`${url}${dataId}`, {
            headers: {
                'Cache-Control': 'no-cache, no-store, must-revalidate',
                Pragma: 'no-cache',
                Expires: 0,
            },
        });
        if (response.ok) {
            return response.json();
        }
        throw new Error('invalidCode');
    };
    
    export default getDataById;
    

    In my App.js file (my entry point to the application) I add the event listener:

    NetInfo.isConnected.addEventListener(
                'connectionChange',
                onInitialNetConnection,
            );
    

Comments are closed.