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

Comments

Projects
None yet
@rkostrab

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

This comment has been minimized.

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

This comment has been minimized.

lixiaolihua commented Jul 7, 2016

+1

@ryankask

This comment has been minimized.

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

This comment has been minimized.

Thorbenandresen commented Jul 9, 2016

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

@knowbody

This comment has been minimized.

Contributor

knowbody commented Jul 11, 2016

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

This comment has been minimized.

Hamiltontx commented Jul 16, 2016

+1

@lincwee

This comment has been minimized.

lincwee commented Jul 18, 2016

we have found this bug in 0.29.2..

@EastLee

This comment has been minimized.

EastLee commented Jul 20, 2016

we have found this bug in 0.28

@rkostrab rkostrab closed this Jul 26, 2016

@rkostrab rkostrab reopened this Jul 27, 2016

@rkostrab

This comment has been minimized.

rkostrab commented Jul 27, 2016

0.30.0 still not working

@ryankask

This comment has been minimized.

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

This comment has been minimized.

AdityaAthavale commented Jul 29, 2016

I noted the same Issue today

@uc-spr

This comment has been minimized.

uc-spr commented Aug 1, 2016

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

@xing-zheng

This comment has been minimized.

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

This comment has been minimized.

Contributor

xing-zheng commented Aug 1, 2016

@JumalDB

This comment has been minimized.

JumalDB commented Aug 24, 2016

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

@ivanzotov

This comment has been minimized.

Contributor

ivanzotov commented Sep 5, 2016

same to 0.32

@florentsorel

This comment has been minimized.

florentsorel commented Sep 10, 2016

@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

This comment has been minimized.

Contributor

knowbody commented Sep 11, 2016

@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

This comment has been minimized.

liutian1937 commented Oct 14, 2016

+1

@danleveille

This comment has been minimized.

danleveille commented Oct 18, 2016

I'm having this issue on v0.34.1

Edit: Updated to v0.35.0 and same problem.

@IrfyNaz

This comment has been minimized.

IrfyNaz commented Oct 25, 2016

same on v0.35.0

@Dnld

This comment has been minimized.

Dnld commented Oct 26, 2016

I am having the same issue on v0.36.0

@Ehesp

This comment has been minimized.

Contributor

Ehesp commented Oct 31, 2016

@knowbody snippet works for me in 0.36

@afilp

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

wszrf7758521 commented Nov 23, 2016

0.34.1 still not working

@nickythorne

This comment has been minimized.

nickythorne commented Dec 1, 2016

Same issue with RN 0.37.0

@finkbit

This comment has been minimized.

finkbit commented Mar 21, 2018

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.

@1335382915

This comment has been minimized.

1335382915 commented Apr 13, 2018

@MichaelPintos It works for me, thanks.

@yuyao110120

This comment has been minimized.

yuyao110120 commented Apr 17, 2018

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.

@kylevdr

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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 !

@AbdallaMohamed

This comment has been minimized.

AbdallaMohamed 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

This comment has been minimized.

Contributor

SudoPlz commented May 2, 2018

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

@nol13

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

nlindroos commented May 28, 2018

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

This comment has been minimized.

Contributor

SudoPlz commented May 29, 2018

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

@nlindroos

This comment has been minimized.

nlindroos commented May 29, 2018

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.

@assafb81

This comment has been minimized.

assafb81 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

This comment has been minimized.

Contributor

octopitus commented Jun 3, 2018

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

@martinentelect

This comment has been minimized.

martinentelect commented Jun 4, 2018

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.

@assafb81

This comment has been minimized.

assafb81 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

This comment has been minimized.

YashGadle commented Jun 6, 2018

@assafb81 Thank you! This helped my use case.

@tannera

This comment has been minimized.

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

This comment has been minimized.

sksahil030 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")
  }
@assafb81

This comment has been minimized.

assafb81 commented Jul 5, 2018

@tannera,
check on real android device and not emulator

@mtt87

This comment has been minimized.

mtt87 commented Jul 20, 2018

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

@laukaichung

This comment has been minimized.

laukaichung commented Aug 16, 2018

Still not fixed on 0.56

@hramos

This comment has been minimized.

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

This comment has been minimized.

Collaborator

brentvatne commented Aug 29, 2018

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.