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

NetInfo.isConnected.addEventListener only works in root componentDidMount #18130

Closed
ekimlinger opened this issue Feb 27, 2018 · 9 comments
Closed
Labels
Bug Resolution: Locked This issue was locked by the bot.

Comments

@ekimlinger
Copy link

Is this a bug report?

Yes

Have you read the Contributing Guidelines?

Yes

Environment

Android only

Environment:
OS: macOS Sierra 10.12.6
Node: 8.9.1
Yarn: 1.3.2
npm: 5.5.1
Watchman: 4.9.0
Xcode: Xcode 9.2 Build version 9C40b
Android Studio: 3.0 AI-171.4443003

Packages: (wanted => installed)
react: 16.2.0 => 16.2.0
react-native: 0.53.3 => 0.53.3

Steps to Reproduce

NetInfo.isConnected.addEventListener is not being registered unless on the root App.js component on componentDidMount.

(Write your steps here:)

  1. Under your App.js file, create an event listener for NetInfo. Note that this works just fine.
  2. Create a child component (class component in my case) that renders in App.js
  3. Under the child component in the componentDidMount or componentWillMount, create an event listener.
  4. The listener here on your child component will never be called.

Expected Behavior

Expected the same functionality for registering an event listener on NetInfo to be the same no matter where it is called in the app.

Actual Behavior

The function specified in NetInfo.isConnected.addEventListener never gets called on android unless it is in componentDidMount on App.js.

Reproducible Demo

Snippet of App.js containing the child component:

class App extends React.Component {

    //This works just fine if uncommented:
    // componentDidMount() {
    //     NetInfo.isConnected.addEventListener(
    //         'connectionChange',
    //         isConnected => {
    //             console.log('Connectedxc: ', isConnected);
    //         }
    //     );
    // }

    render() {
        return (
               <NetworkStatusProvider>
                     <Text>Some text</Text>
               </NetworkStatusProvider>
        );
    }
}

And in the NetworkStatusProvider:

import {NetInfo} from 'react-native';

class NetworkStatusProvider extends React.Component {

    componentDidMount() {
        NetInfo.isConnected.addEventListener(
            'connectionChange',
            (value) => {
                  console.log('Expected to see value logged: ', value);
            }
        );
    }

    render() {
        return this.props.children;
    }
}
@react-native-bot react-native-bot added the Platform: macOS Building on macOS. label Mar 20, 2018
@hramos hramos removed the Platform: macOS Building on macOS. label Mar 29, 2018
@JitendraLakhmani1824
Copy link

Any Update?

@ekimlinger
Copy link
Author

Didn't find a specific fix for the issue, however our team found a workaround for it.

We are using redux-saga in order to manage the connectivity state of the app and using an event channel to monitor it:

// Forked off of our root saga
export function* networkConnectivitySaga() {
    const channel = yield call(createNetworkChangeChannel);
    try {
        while (true) {
            const connected = yield take(channel);
            // Dispatches an action to update our redux state
            yield put({ type: UPDATE_NETWORK_STATUS, connected });
        }
    } finally {
        if (yield cancelled()) {
            channel.close();
        }
    }
}

export function createNetworkChangeChannel() {
    return eventChannel(emitter => {
        NetInfo.isConnected.addEventListener('connectionChange', emitter);
        return () => { //Function to unsubscribe
            NetInfo.isConnected.removeEventListener(
                'connectionChange',
                emitter
            );
        };
    });
}

Not sure why this works and setting it up in a componentDidMount doesn't.

@gmaggio
Copy link

gmaggio commented Aug 29, 2018

My workaround is to use NetInfo.isConnected.fetch. But not sure of its efficiency, though, since it gets called every time it mounts.

import {NetInfo, Platform} from 'react-native';

class NetworkStatusProvider extends React.Component {

    componentDidMount() {
        // Android hack for NetInfo addEventListener
        // not being detected on initial mount
        if (Platform.OS === 'android') {
            NetInfo.isConnected.fetch().then(isConnected => {
                console.log('Expected to see value logged: ', isConnected);
            })
        }
        NetInfo.isConnected.addEventListener(
            'connectionChange',
            (value) => {
                console.log('Expected to see value logged: ', value);
            }
        );
    }

    render() {
        return this.props.children;
    }
}

@robmoorman
Copy link

In my experience the NetInfo.isConnect returns offline for Android (when I'm online)

@rszalski
Copy link

@ekimlinger Could you retest this issue in newest version of React Native (that would be v0.57.1 as of now)?

I'm using React Native v0.57.0 and it works fine on physical Android device (OnePlus6, Android v8.1.0). It detects offline/online changes for isConnected when changing Wifi On/Off and/or cellular On/Off.

I also tested this on iOS Simulator (iPhone 6, iOS 12) on macOS Mojave. The iOS simulator correctly interprets my Mac's Wifi switching off, but doesn't pick up an event when WiFi is switched back on.

My component structure:

index.js ---v
     <App> ---v
          <Provider store> ---v
                <ThemeProvider> ---v
                        <RootContainer> ---V 
                               <SaveAreaView>
                                       <InternetConnectionCheckerContainer />  // subscribes to `NetInfo` events

This is how I set up my subscribes/unsubscribes inside <InternetConnectionCheckerContainer />:

_handleFirstConnectivityChange = isConnected => {
   isConnected ? this.props.internetConnected() : this.props.internetDisconnected()
 }

 componentDidMount () {
   NetInfo.isConnected.addEventListener(
     'connectionChange',
     this._handleFirstConnectivityChange
   )
 }

 componentWillUnmount () {
   NetInfo.isConnected.removeEventListener(
     'connectionChange',
     this._handleFirstConnectivityChange
   )
 }

@ghost
Copy link

ghost commented Oct 26, 2018

Still not working for me on react-native 0.57.3

My component structure:
`<index.js> ---v

<App> ---v
   <Router> ---v
      <Menu> ---v   // subscribes to NetInfo and works
          <Provider> ---v  // subscribes to NetInfo and DOESN'T work
              <Component>  // subscribes to NetInfo and DOESN'T work

`

@prasad456
Copy link

@gmaggio
how use this class as a separate component or within component. And how to implement to get network status?
Plz explain I'm a newbie to react-native (0.57.2)

@ue
Copy link

ue commented Jan 28, 2019

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

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

  _handleConnectionChange = (isConnected) => {
    this.props.dispatch(connectionState({ status: isConnected }));
  };

I am using as the example. When it change at the first time it working grate but when connectivity change again (online to offline or vice versa) its not working so event listener becomes dysfunctional. It just working once
I am toggling from wifi settings.

What I am wrong?

@cpojer
Copy link
Contributor

cpojer commented Feb 12, 2019

Heads up: we moved react-native-netinfo into its own repository, which should allow for making changes and fixes much faster. Please continue the discussion about this issue there: react-native-netinfo/react-native-netinfo#13

@cpojer cpojer closed this as completed Feb 12, 2019
@facebook facebook locked as resolved and limited conversation to collaborators Feb 12, 2020
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Feb 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

10 participants