Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS: NetInfo.isConnected returns always false #8615

Closed
rkostrab opened this issue Jul 6, 2016 · 139 comments
Closed

iOS: NetInfo.isConnected returns always false #8615

rkostrab opened this issue Jul 6, 2016 · 139 comments
Labels
Help Wanted :octocat: Issues ideal for external contributors. Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.

Comments

@rkostrab
Copy link

rkostrab commented Jul 6, 2016

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.

@hithacker
Copy link

hithacker commented Jul 7, 2016

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.

@lixiaolihua
Copy link

+1

@ryankask
Copy link
Contributor

ryankask commented Jul 7, 2016

I've reported the same issue before: #8469

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

@thorbenandresen
Copy link

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

@knowbody
Copy link
Contributor

I solved it this way:

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

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

@Hamiltontx
Copy link

+1

@lincwee
Copy link

lincwee commented Jul 18, 2016

we have found this bug in 0.29.2..

@EastLee
Copy link

EastLee commented Jul 20, 2016

we have found this bug in 0.28

@rkostrab rkostrab reopened this Jul 27, 2016
@rkostrab
Copy link
Author

0.30.0 still not working

@ryankask
Copy link
Contributor

ryankask commented Jul 27, 2016

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

Note that I previously reported the bug here: #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.

@AdityaAthavale
Copy link

I noted the same Issue today

@uc-spr
Copy link

uc-spr commented Aug 1, 2016

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

@xing-zheng
Copy link
Contributor

xing-zheng commented Aug 1, 2016

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

@xing-zheng
Copy link
Contributor

@facebook-github-bot bug

@JumalDB
Copy link

JumalDB commented Aug 24, 2016

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

@ivanzotov
Copy link
Contributor

same to 0.32

@florentsorel
Copy link

@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

@knowbody
Copy link
Contributor

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

@liutian1937
Copy link

+1

@danleveille
Copy link

danleveille commented Oct 18, 2016

I'm having this issue on v0.34.1

Edit: Updated to v0.35.0 and same problem.

@IrfyNaz
Copy link

IrfyNaz commented Oct 25, 2016

same on v0.35.0

@ghost
Copy link

ghost commented Oct 26, 2016

I am having the same issue on v0.36.0

@Ehesp
Copy link
Contributor

Ehesp commented Oct 31, 2016

@knowbody snippet works for me in 0.36

@afilp
Copy link

afilp commented Nov 6, 2016

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

@ryankask
Copy link
Contributor

ryankask commented Nov 6, 2016

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.

@wszrf7758521
Copy link

0.34.1 still not working

@nickythorne
Copy link

Same issue with RN 0.37.0

@kylevdr
Copy link

kylevdr commented Apr 19, 2018

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

@SudoPlz
Copy link
Contributor

SudoPlz commented Apr 19, 2018

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

@wilomgfx
Copy link

wilomgfx commented Apr 19, 2018

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

@AbdallaElabd
Copy link

AbdallaElabd commented May 2, 2018

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

@SudoPlz
Copy link
Contributor

SudoPlz commented May 2, 2018

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

@nol13
Copy link

nol13 commented May 11, 2018

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

@woodpav
Copy link

woodpav commented May 16, 2018

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.

@nlindroos
Copy link

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.

@SudoPlz
Copy link
Contributor

SudoPlz commented May 29, 2018

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

@nlindroos
Copy link

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.

@b-asaf
Copy link

b-asaf commented May 31, 2018

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

@octopitus
Copy link
Contributor

octopitus commented Jun 3, 2018

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

@martinentelect
Copy link

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.

@b-asaf
Copy link

b-asaf commented Jun 5, 2018

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

@YashGadle
Copy link

@assafb81 Thank you! This helped my use case.

@tannera
Copy link

tannera commented Jun 11, 2018

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

@sahil-innostax
Copy link

sahil-innostax commented Jul 4, 2018

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

@b-asaf
Copy link

b-asaf commented Jul 5, 2018

@tannera,
check on real android device and not emulator

@mtt87
Copy link

mtt87 commented Jul 20, 2018

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

@laukaichung
Copy link

Still not fixed on 0.56

@hramos
Copy link
Contributor

hramos commented Aug 22, 2018

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

@facebook facebook locked as resolved and limited conversation to collaborators Aug 22, 2018
@brentvatne
Copy link
Collaborator

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.

matt-oakes pushed a commit to matt-oakes/react-native that referenced this issue Feb 7, 2019
Summary:
This is fixing facebook#8615. The problem was that, on initialization, the `_connectionType` variable was still set to its default value of `RCTConnectionTypeUnknown`. The exposed API method did nothing to determine this unless a subscription had be established and then the method would simply return the last reported value. Instead, the exposed oneshot API call now actually checks the connection status through the same methods as the subscription and updates RCTNetInfo’s values before returning.

In order to avoid reporting events without a subscription, a flag is set and unset on calls to start/stopObserving.

- start app
- observe the (in)correct reporting of the manual status
- change network status to offline
- press refresh
- observe the manual fetch
- start subscription
- change network status to online
- press refresh to show that the manual refresh works (only now working for current RN version)
- change network status to offline
- stop subscription
- change network status to online
- press refresh to show manual refresh does(n't) work without subscription
- start subscription to show it updates to current

Current Behavior: https://drive.google.com/file/d/1Ods6HORgp_vfm1mQVjGwhtH1D7issxjo/view?usp=sharing
Fixed Behavior: https://drive.google.com/file/d/11H1UOF33LeMGvXEOoapU62ARDSb7qoYv/view?usp=sharing

[IOS] [BUGFIX] [Libraries\Network\RCTNetInfo.m] - Fixed facebook#8615, `iOS: NetInfo.isConnected returns always false`, by decoupling the fetch from the status of the subscription.
Closes facebook#17397

Differential Revision: D7102771

Pulled By: hramos

fbshipit-source-id: ea11eb0b1a7ca641fc43da2fe172cf7b2597de4a
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Dec 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Help Wanted :octocat: Issues ideal for external contributors. Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

Successfully merging a pull request may close this issue.