React-native: iOS: NetInfo.isConnected returns always false

Created on 6 Jul 2016  ·  139Comments  ·  Source: facebook/react-native

I am currently running RN 0.28.0...

NetInfo.isConnected.fetch().then(isConnected => {
      // variable isConnected is always false
    });

I would do a PR but I can't code for iOS.

Help Wanted iOS Locked

Most helpful comment

According to @robertodias180 suggestions I came up to wrapper for isConnected,
It seems to work, but I wonder if it will work in all cases

export function isNetworkConnected() {
  if (Platform.OS === 'ios') {
    return new Promise(resolve => {
      const handleFirstConnectivityChangeIOS = isConnected => {
        NetInfo.isConnected.removeEventListener('change', handleFirstConnectivityChangeIOS);
        resolve(isConnected);
      };
      NetInfo.isConnected.addEventListener('change', handleFirstConnectivityChangeIOS);
    });
  }

  return NetInfo.isConnected.fetch();
}

All 139 comments

I can also reproduce this with RN 0.29.0. I was running on 0.26.2 earlier and it worked fine with it. Going to try building from source and debug.

+1

I've reported the same issue before: https://github.com/facebook/react-native/issues/8469

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

+1 and same issue with NetInfo.fetch().done() - always returns unknown

I solved it this way:

componentDidMount() {
  const dispatchConnected = isConnected => this.props.dispatch(setIsConnected(isConnected));

  NetInfo.isConnected.fetch().then().done(() => {
    NetInfo.isConnected.addEventListener('change', dispatchConnected);
  });
}

+1

we have found this bug in 0.29.2..

we have found this bug in 0.28

0.30.0 still not working

The relevant code hasn't changed so it makes sense that it's still not working.

Note that I previously reported the bug here: https://github.com/facebook/react-native/issues/8469 where it details the cause and has sample code attached. Because of this, I think it makes sense to leave this closed.

The number of open RN issues grows daily so it's important to do our part and consolidate where possible.

I noted the same Issue today

I am using 0.30.0 version , And i'm also found this error.

the same issue to me, I am using [email protected] 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})
    }
)

@facebook-github-bot bug

I am having this issue on 0.31, will this be fixed?

same to 0.32

@knowbody How your snippet work? I need to define a setIsConnected method in my class or as a global function or anything else? Because, actually I have an error who said Can't find variable: setIsConnected

@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;

+1

I'm having this issue on v0.34.1

Edit: Updated to v0.35.0 and same problem.

same on v0.35.0

I am having the same issue on v0.36.0

@knowbody snippet works for me in 0.36

@Dnld: @Ehesp says that it works on v.036, you and 5 others not? Is this not solved eventually? I used to have problems with 0.33 too, and I would like to upgrade. Thanks.

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.

0.34.1 still not working

Same issue with RN 0.37.0

@xing-zheng for some reason your solution only returns 'MOBILE', even when I turn off the wifi on my computer, which should reflect in my emulator. Any idea why?

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

Same issue with RN 0.38.0

same in 0.39 too

When I try the addEventListener solution NetInfo only detects one or two connection changes. For example, if I start with a connection and then drop it Netinfo will detect that, but if I reconnect it will fail to detect that I'm now connected. NetInfo is producing an awful lot of false positives in my app, even with the workaround. Is anyone else experiencing the same?

I had to build a weird workaround in order to solve this. For some reason one method works on android and the other on iOS. A fix to this would be great.

function handleFirstConnectivityChange(isConnected) {
    if (!sConnected) {
     // do action
    } 
    NetInfo.isConnected.removeEventListener('change', handleFirstConnectivityChange);
}

if (Platform.OS === 'ios') {
    NetInfo.isConnected.addEventListener('change', handleFirstConnectivityChange); 
} else {
    NetInfo.isConnected.fetch().then(isConnected => {
    if (!sConnected) {
        // do action
    } 
}

@robertodias180 it's not working .

RN- 0.39+

function handleFirstConnectivityChange(isConnected) {
if (!sConnected) {
// do action
}
NetInfo.isConnected.removeEventListener('change', handleFirstConnectivityChange);
}

if (Platform.OS === 'ios') {
NetInfo.isConnected.addEventListener('change', handleFirstConnectivityChange);
} else {
NetInfo.isConnected.fetch().then(isConnected => {
if (!sConnected) {
// do action
}
}

Can you please help me out?

@imbudhiraja does it work on any of the platforms?

No it was not working on any of platform

Thanks
Manish Budhiraja

On Jan 3, 2017 8:12 PM, "Roberto Dias" notifications@github.com wrote:

@imbudhiraja https://github.com/imbudhiraja does it work on any of the
platforms?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/react-native/issues/8615#issuecomment-270128504,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AVTjXHSe8OcVq8fQ5XVk8hh9XXHfHFVZks5rOl5ggaJpZM4JGaBc
.

It looks like this may be two problems:

  1. isConnected.fetch seems to be broken on iOS - the fix should be straightforward. The workaround posted by @robertodias180 makes sense because it queries the native code with another method.
  2. The NetInfo flakyness described by @Aristekrat . This is more worrying- can somebody help provide a detailed way to reproduce this problem? Then I should be able to help get it fixed.

RN 0.38.1 and earlier, iOS Simulator.

componentDidMount() {
    NetInfo.isConnected.fetch().then(this._handleConnectionInfoChange);
    NetInfo.isConnected.addEventListener(
        'change',
        this._handleConnectionInfoChange
    );
 }

 componentWillUnmount(){
     NetInfo.isConnected.removeEventListener(
        'change',
        this._handleConnectionInfoChange
    );
 }

_handleConnectionInfoChange(isConnected){
    this.props.connectActions.netInfo(isConnected);

    dbg('connected', isConnected);

};

The initial NetInfo.isConnected.fetch().then(this._handleConnectionInfoChange); correctly retrieves the current connection status. However, subsequent changes to the connection status are not captured by the eventListener.

I have been having this issue for many RN version now.

@imbudhiraja i ended up change the code for something "cleaner". I have an util that has the current state of the network connection. This is working on both platforms. I initializeConnection when the app opens and then isConnected when i need. Please not that it may take some until the NetInfo gets the connection status when the app opens (especially on android). I just made a delay until hasConnection !== null. Hope it helps

const hasConnection = null;

export const initializeConnection = () => {

  const dispatchConnected = isConnected => { hasConnection = isConnected; };

  NetInfo.isConnected.fetch().then().done(() => {
    NetInfo.isConnected.addEventListener('change', dispatchConnected);
  });

}

export const isConnected = () => {
  NetInfo.fetch().done((reach) => {
    console.log('Initial: ' + reach);
  });
  return hasConnection;
}

Tried something similar, I keep running into the situation that the eventListener doesn't detect it when the connection returns (on the simulator).

Reload app without internet connection => Detected
Turn internet back on => NOT detected

Reload app with internet connection => Detected
Turn internet off => Detected
Turn internet back on => NOT detected

@autobind
export default class ConnectionToast extends React.Component {

    constructor(props){
        super(props);
    }

    componentDidMount() {
        NetInfo.isConnected.fetch()
            .then(this._handleConnectionInfoChange)
            .done(this._addListener);
     }

     componentWillUnmount(){
         this._removeListener();
     }

     _addListener(){
         NetInfo.isConnected.addEventListener(
             'change',
             this._handleConnectionInfoChange
         );
     }

     _removeListener(){
         NetInfo.isConnected.removeEventListener(
            'change',
            this._handleConnectionInfoChange
        );
     }

    _handleConnectionInfoChange(isConnected){
        this.props.connectActions.netInfo(isConnected);

        dbg('connected', isConnected);

        // this._removeListener();
        // this._addListener();

    }

[...]

Tried removing and re-adding the listener with every change, but no joy.

@mschipperheyn I am experiencing the exact same issue using the approach that @knowbody posted earlier on.

The docs also imply that it would only handle the first change via handleFirstConnectivityChange. Is this correct, or should it detect all subsequent changes?

Make sure you have

set in your android manifest file. This one tripped me up.

Same issue with RN 0.41.0

in iOS, not add listener and not register SCNetworkReachabilitySetCallback. surely not working. what is the design purpose?

same to 0.41.2

@djohnkirby Your comment is missing the XML I think you meant to post - can you Edit it please?

The line to add to you AndroidManifest.xml is:

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

0.39.2: Same issue. Not only NetInfo fetch result is always false, but it also detects a connexion status change quickly after the app starts

0.42.0: Same issue. I also described my problem here: https://stackoverflow.com/questions/42642034/check-for-internet-connection-returns-wrong-results
I am testing on iOS and macOS Sierra.

UPDATE: My problem was because of testing on the simulator, on a real device everything is working. Answered in the above link.

I have the same issue :(

NetInfo.isConnected.fetch().then((isConnected) => { console.log(isConnected); });
// always return false

In case that someone wants to know if the app is running on the simulator or not: http://stackoverflow.com/a/34732015/552669

It's not a bug. The native module RCTNetInfo is a subclass of RCTEventEmitter, so we must add a observer to trigger the startObserving method.
In your app launch process, add a arbitrary observer to NetInfo, then you can call fetch function.(NetInfo.isConnected indeed call the fetch function)

According to @robertodias180 suggestions I came up to wrapper for isConnected,
It seems to work, but I wonder if it will work in all cases

export function isNetworkConnected() {
  if (Platform.OS === 'ios') {
    return new Promise(resolve => {
      const handleFirstConnectivityChangeIOS = isConnected => {
        NetInfo.isConnected.removeEventListener('change', handleFirstConnectivityChangeIOS);
        resolve(isConnected);
      };
      NetInfo.isConnected.addEventListener('change', handleFirstConnectivityChangeIOS);
    });
  }

  return NetInfo.isConnected.fetch();
}

Same issue. 0.40

I am experiencing the same issue

0.42.3 - I experienced the same issue running iOS on both the simulator and an actual device. Using the solution from @Knight704 has mitigated the problem.

Same on 0.42.3

same on 0.43.1

Seeing this on 0.40

having this issue as well. Was able to have it work randomly then it stopped working.

@Knight704's solution worked at first for me, but for some reason once I call it once from inside the second layer of a navigator in a modal, the function stops working (handleFirstConnectivityChangeIOS is never called), even after I close the modal. Very odd behavior, no clue why this isn't working or if it is something else in my codebase that is not working well with NetInfo.

what am I missing?

    this.state = {
            isConnected: null,
     }
    componentDidMount() {
        console.log('first one ', this.state.isConnected)
        NetInfo.isConnected.addEventListener(
            'change',
            this._handleConnectivityChange
        );
        console.log('second ', this.state.isConnected)
        NetInfo.isConnected.fetch().done(
            (isConnected) => {this.setState({isConnected});}
        );
        console.log('third ', this.state.isConnected)
    }
    componentWillUnmount(){
        console.log('did it unmount ', this.state.isConnected)
        NetInfo.isConnected.removeEventListener(
            'change',
            this._handleConnectionInfoChange
        );
        console.log('it did unmount ', this.state.isConnected)
    }
    _handleConnectivityChange = (isConnected) => {
        this.setState({
            isConnected,
        });
    };
   render() {
      console.log('fourth ', this.state.isConnected)
        if(this.state.isConnected === false){
            const connectAlert = (Alert.alert(
                'ERROR',
                'No connection bro!',
                [
                    {text: 'OK'},
                ]
            ))
        }
        return ()
}

so when i run it, it gives me alert sometimes, not always....

these are the console logs return when it gives me alert even when there's connection :

'fourth ', null
'first one ', null
'second ', null
'third ', null
'fourth ', false
'fourth ', true

Experiencing the same issue as @SteffeyDev when I use the fix from @Knight704 in https://github.com/facebook/react-native/issues/8615#issuecomment-287977178 In most cases, this works just fine, however when I have pushed or popped modals the same code will never resolve as I am assuming the change event was already emitted.

I noticed that under these conditions, NetInfo.fetch() would return an unknown state (this will trigger a false under NetInfo.isConnected.fetch() and so I was able to work around it with the following modification to the original workaround:

export function isNetworkConnected() {
  return NetInfo.fetch().then(reachability => {
    if (reachability === 'unknown') {
      return new Promise(resolve => {
        const handleFirstConnectivityChangeIOS = isConnected => {
          NetInfo.isConnected.removeEventListener('change', handleFirstConnectivityChangeIOS);
          resolve(isConnected);
        };
        NetInfo.isConnected.addEventListener('change', handleFirstConnectivityChangeIOS);
      });
    }
    reachability = reachability.toLowerCase();
    return (reachability !== 'none' && reachability !== 'unknown');
  });
}

The unknown condition is only triggered on iOS since Android returns UNKNOWN. This is also the reason for lowercasing before returning the status since this should more or less retain the existing behavior from NetInfo.isConnected.fetch.

same in 0.44

At first I observed that NetInfo only wants to return the network status change after one cycle ( on -> off ). It turned out that it only has that problem in the simulator. On a real device it fires the callback properly even for multiple connect / disconnect cycles.

Sample code

  NetInfo.addEventListener( 'change', this._onConnectivityChange );

  _onConnectivityChange(connType) {
    // Do something with connType...
  }

This issue bugged me for a while and I indirectly ended up creating a small utility library focused on RN offline/online detection, encompassing typical React patterns and a nice integration with redux.

It works properly on real devices, both Android and iOS. However, I can also corroborate that sometimes the listener is not triggered in the iOS simulator and the connectivity state gets inconsistent. I haven't yet tried the solutions proposed by @knight704 and @Ignigena (here and here respectively) but will probably test them out soon when I get some time.

A PR is also very welcome in case of more folks confirming that those solutions work like a charm!

Please fix.

If this is unlikely to get fixed soon, can we at least get the docs updated to indicate that this doesn't work in iOS?

@jpb12 maybe it's worth making the PR and seeing if they merge it. May actually get this more visible as it seems to be forgotten about.

I am facing this issue in Android version. It seems to be related to going to the background and coming back to the foreground. Unfortunately I can not reliably reproduce this issue but it definitely happens after several background/foreground transitions. Especially if connection status has been changed that time

When it happens
NetInfo.isConnected.fetch().then(isConnected => {...}) always returns false
NetInfo.fetch().then((reach) => {...}) always returns NONE
adding/removing listeners do not help

I would be very grateful for any reliable way to detect real connection status

I'm facing a strange behaviour because isConnected return true when connect to wifi (so far is ok) but if the modem don't reach internet, isConnected is still true. I'm not really sure how to check effectively the internet connection, not just the network connection. Any ideas? Thanks

@kodatech This module should help you resolve that issue. I have used it recently on a project and highly recommend it https://github.com/rauliyohmc/react-native-offline

Many thanks @craigcoles

@Knight704 thanks bro.

@craigcoles Do you have any working code that I could follow?

@nmfzone I don't have anything that I can show you, but there is plenty of code examples in the Readme 😃

I am using the Netinfo listener events as follows, it works great on both platforms.
"react-native": "0.43.4",

componentDidMount(){
        NetInfo.isConnected.addEventListener('change', this._handleConnectivityChange);

    }

    componentWillUnmount(){
        NetInfo.isConnected.removeEventListener('change', this._handleConnectivityChange);
    }

    _handleConnectivityChange = (isConnected) => {
         console.warn(isConnected);
    }

@sumesh1993 From my experience if the Android app has been minimized (in background) it does not react on 'change' event. Tested on my Galaxy Note 5, Android 7.0

The module https://github.com/rauliyohmc/react-native-offline which was recommended above just continuously pinging https://google.com. It works but I would prefer to get this bug fixed

That makes sense since Android apps are suspended while in the background. To receive events, you'd need to create a service which will continue to run even while the app is suspended.

Alternatively, you could add an onResume handler to the app and query the offline status then. That should be simpler than creating and managing a service.

@alsh76 for me its working when the app is in background, it doesn't work when the app is killed from the multitasking menu.
I resolved that by calling the following function whenever my home screen is launched.
if(Platform.OS === 'android'){ NetInfo.isConnected.fetch().then(isConnected => { if(!isConnected) return; //Do something }); }

Met the same problem with android virtual device. But the thing is it was okay a few days ago and still doing so on iOS device and emulator. Did somebody find stable and correct way to get network connection status?

Thanks @sumesh1993 that did the trick for me in iOS!
@igorarkhipenko did you try his suggestion?

Hi did you add permission for example android need to add
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

just a small update on the solutions by @Knight704 and @Ignigena as NetInfo.fetch is deprecated now. This did the trick for me:
```
const isNetworkConnected = () => {
return NetInfo.getConnectionInfo().then(reachability => {
if (reachability.type === 'unknown') {
return new Promise(resolve => {
const handleFirstConnectivityChangeIOS = isConnected => {
NetInfo.isConnected.removeEventListener('connectionChange', handleFirstConnectivityChangeIOS);
resolve(isConnected);
};
NetInfo.isConnected.addEventListener('connectionChange', handleFirstConnectivityChangeIOS);
});
}
return (reachability.type !== 'none' && reachability.type !== 'unknown')
});
}

Imho NetInfo.isConnected.fetch() is an important feature and should be fixed asap!

@javache @sahrens @davidaurelio @janicduplessis @hramos @shergin @rigdern is there any timeline for this?

Thx!

@pensierinmusica This is community driven project, so I would love to land good PR.

@shergin I thought React Native was created, maintained and used internally by Facebook, and released under a BSD 3-clause license for this reason. So I assumed Facebook staff would fix bugs, especially important ones. Anyways, good to know that PRs are welcome!

cc @rigdern

Lots on RN core code is written and maintained by the community.

And there are many features and functionality not used by Facebook so it's hard for us to prioritize them and prefer community PRs where the author can verify the fix for their bug/usecase.

I am also Having issue in react 0.47.0 with ios .

@pensierinmusica this issue should most definitely be prioritised. How difficult can is be to have a boolean return from the .isConnected() ?

Alright here's an out of the box workaround that should do the trick (well it does for me). I send out a http request to a site that I know will be active and evaluate the response.

I have initialised a repo that should work out of the box. https://github.com/JamesDorrian/NetInfoCheckConnection/tree/master

Note: be sure to change the httpAddress variable from https://www.galwaydaily.com to something else (maybe google.com) as I cannot guarantee that is will always be live. I hope this helps anyone frustrated by NetInfo!

@pensierinmusica @anujsinghwd

@JamesDorrian thanks, I ended up doing something similar, pinging "google.com".

Here's the snippet:

// /utilities/connectivity.js

import { Alert } from 'react-native';

export function warning () {
  Alert.alert(
    'No connection',
    'Mmm... you seem to be offline'
  );
};

export async function checkAsync () {
  try {
    const res = await fetch('https://google.com');
    if (res.status === 200) return true;
  } catch (e) {
    warning();
  }
  return false;
};

Still, this is just a temporary workaround, and I think that NetInfo.isConnected should be fixed asap!

let isConnected = false;

Platform.OS === "ios" 
  ? (isConnected = await fetch("https://www.google.com"))
  : (isConnected = await NetInfo.isConnected.fetch());

Platform.OS === "ios" && (isConnected.status = 200)
  ? (isConnected = true)
  : (isConnected = false);

console.log(isConnected); //Result

Can we stop with the +1 comments on this issue please, this is what reactions are used for.

ios:
first request. if server crash,phone has wifi.
NetInfo.isConnected.fetch().then((isConnected) => {alway false}
0.49.3.

@kddc your solution seems to work fine in development 👍

Just add Reachability Library into your XCode project from Apple which served here, it's the solution.

@fuatsengul I have added Reachability project as a library in my Xcode project, but still the issue is not solved, could you please brief me what else needs to be done to get the issue resolved ? Thanks.

The problem appears to be only with the fetch api.. however, adding event listener is working on iOS.. However, addEventListener doesn't work on android, so you need to use fetch api :)

Here's my snippet to make it work on both worlds:

function handleFirstConnectivityChange(isConnected) {
  console.log('Then, is ' + (isConnected ? 'online' : 'offline'))
  NetInfo.isConnected.removeEventListener(
    'connectionChange',
    handleFirstConnectivityChange,
  )
}

if (Platform.OS === 'android') {
    NetInfo.isConnected.fetch().then(isConnected => {
      console.log('First, is ' + (isConnected ? 'online' : 'offline'))
    })
  } else {
    NetInfo.isConnected.addEventListener(
      'connectionChange',
      handleFirstConnectivityChange,
    )
  }

Its showing offline in IOS even though its connected
RN -- 0.50

NetInfo.isConnected.fetch().then(isConnected => { console.log('First, is ' + (isConnected ? 'online' : 'offline')); });

@kddc thanks for the workaround.
I am encountering an issue with it in my iOS device and scenario is as follows:

  1. ios -> airplane mode is on
  2. perform fetch -> getting 'network error', isConnected is false and reachability.type is none
  3. ios -> airplane mode is off
  4. perform fetch -> getting 'network error', isConnected is false and reachability.type is none

The entire time the application is running, in the background while changing airplane mode.
Only restarting the app "catch" the new network connection.

+1

+1

Thanks for the fix @alburdette619
So, this is fixed in will be available in version 0.54?

@assafb81 I'm not sure, apparently they are landing it internally and I'm not sure what the process for that is, do you?

When your pull request gets merged, Facebook first incorporates it into their internal React Native repo and runs additional tests on it among other things. When that is successful, the change gets exported back to the GitHub repo.

By looking at your pull request's activity, you can see your commit is now merged on GitHub. By looking at the commit info, you can see which branches it's included in. Currently, it's only in the "master" branch:

image

For comparison, if you look at an older commit you can see it appears in a number of branches:

image

At the beginning of every month, a new release candidate branch is created based on "master". So your change will likely be in the next release candidate at the beginning of March. You can read more about React Native's release schedule in this blog post.

Adam Comella
Microsoft Corp.

Did anyone verify this issue with latest RN 54 ? For me its always returning 'true' now on iOS and on Android it works perfectly fine. Anyone else seeing this issue ?

0.53 always false .. @deepaksasken .. seem i need to disable the code only for android .. Cannot use 0.54 to many bugs.

@alien3d You mean disable it for iOS and keep it only for Android? In Android it works?

@afilp i just follow above example for ios

    if (Platform.OS === "ios") {
            isConnected = await fetch("https://www.google.com");
            if (isConnected) { }
  } else { 
    NetInfo.isConnected.fetch().done(
                (isConnected) => {
                    if (isConnected) { }
} 

I still need around many testing before consider as stable. now using back 0.530

@assafb81 Did you find a solution for the problem with the airplane mode? I am using your solution in 0.53.

@aflip When data is enabled but there is no package still it is returning isConnected true. Have you try to resolve it?

Why is there a removeEventListener. Shouldn't the app be listening to network changes at all times. Anyone?

Also having the same issue as users above. NetInfo event listeners seem to be very unreliable. I have tried many of the above workarounds without stable results. For now I'll rely on fetching https://google.com or a health endpoint on my own servers to ensure my users have an internet connection.

@MichaelPintos It works for me, thanks.

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.

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
  });
});

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);

@SudoPlz I pretty did the same thing on my apps, works just fine. But the NetInfo API should def be fixed haha !

@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
        }
      });

Ok thanks for letting me know @AbdallaMohamed I updated the comment.

same as @kylevdr, worked reliably but adding a small timeout before 2nd call seems to help with flicker where it will disconnected for a split 2nd right after unlocking

Edit: fwiw this works in 55.3, but not 55.4

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.

None of the solutions above worked when running the app in debug mode on an iPhone 8 (React Native 0.55.3, iOS 11.3.1) in the following scenario: Close the app and start it with mobile data and wifi off.

Any subsequent events are lost with all solutions mentioned above (except for @SudoPlz's answer). Only running the application in release mode on the device or in debug mode on a simulator triggered any NetInfo events.

@nlindroos so do you actually confirm that NetInfo works fine on devices that run the release version?

In the specific case of _starting_ the application in offline mode on a physical iOS device, running in release mode was the only working solution to get any NetInfo events to trigger. I haven't tested all related scenarios sufficiently to vouch for this as a generic solution to all NetInfo problems.

I can say that combination of the solutions that @woodpav and @AbdallaMohamed worked for me
I am using RN version 0.55.4

I must ping Google server frequently to check for internet connection 😕

I am using iPhone 8 - 11.3 simulator and on RN version 0.55.4 NetInfo.isConnected.fetch().then(isConnected => console.log('isConnected', isConnected))
Always returns false. This is a problem in production on phone as well. I tried variations of mobile data and wifi.

When switching back to RN version 0.55.3 it seems to be working again.

@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,
        );

@assafb81 Thank you! This helped my use case.

In my case, the event listener works perfectly on iOS but not at all on Android (on the emulator at least).
Are there any workarounds for listeners on Android while still using NetInfo?

    NetInfo.isConnected.addEventListener(
      "connectionChange",
      this.handleConnectionChange
    ); 

Use


this.count = 0
handleConnectivityChange(isConnected) {
   //for iOS
    this.count++
  console.log(isConnected + "isConnected")
  if(this.count > 1){
    console.log(isConnected + "this is the right value")
  }

@tannera,
check on real android device and not emulator

On 0.55.4 this is still a bug, and I just got hit on production 😢

Still not fixed on 0.56

@SudoPlz I've hidden your comment on the 0.57 discussion thread as off-topic. As you know, there's hundreds of open issues in the repo, but that thread is focused on getting a 0.57 release out.

This thread on a closed is pretty much invisible to maintainers, and I'm surprised that six months after a potential fix landed, no one has opened a new issue. If this is something you'd like to see fixed in master, please open a new issue with details, and ideally, send a PR.

Here's a minimal reproducible example (tested on iOS device), with some code from @woodpav shared above to work around the problem commented out at the top: https://snack.expo.io/@notbrent/netinfo-repro.

Was this page helpful?
0 / 5 - 0 ratings