Yes
Yes
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
NetInfo.isConnected.addEventListener is not being registered unless on the root App.js component on componentDidMount.
(Write your steps here:)
componentDidMount or componentWillMount, create an event listener.Expected the same functionality for registering an event listener on NetInfo to be the same no matter where it is called in the app.
The function specified in NetInfo.isConnected.addEventListener never gets called on android unless it is in componentDidMount on App.js.
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;
}
}
Any Update?
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.
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;
}
}
In my experience the NetInfo.isConnect returns offline for Android (when I'm online)
@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 />:
```javascript
_handleFirstConnectivityChange = isConnected => {
isConnected ? this.props.internetConnected() : this.props.internetDisconnected()
}
componentDidMount () {
NetInfo.isConnected.addEventListener(
'connectionChange',
this._handleFirstConnectivityChange
)
}
componentWillUnmount () {
NetInfo.isConnected.removeEventListener(
'connectionChange',
this._handleFirstConnectivityChange
)
}
```
Still not working for me on react-native 0.57.3
My component structure:
`
<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
`
@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)
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?
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: https://github.com/react-native-community/react-native-netinfo/issues/13
Most helpful comment
In my experience the
NetInfo.isConnectreturns offline for Android (when I'm online)