I am using https://github.com/react-native-community/react-native-netinfo to check network connection in my react-native app. How can fetch network connection automatically when Network is lost and the Network is back again?
Below is the code I using.
import React, { Component } from 'react';
import NetInfo from '#react-native-community/netinfo'
import { View, Text,StyleSheet,Dimensions } from 'react-native';
export default class NetStatus extends Component {
constructor(props) {
super (props)
this.state = {
isConnected:''
};
}
componentDidMount() {
this.handleConnectivityChange()
}
componentWillUnmount() {
this.handleConnectivityChange()
}
handleConnectivityChange(){
NetInfo.fetch().then(isConnected => {
this.setState({ isConnected:isConnected.isInternetReachable });
console.log('isConnected : ', isConnected);
})
};
render() {
return (
<View>
{this.state.isConnected === true ?
null
:(
<View style={styles.container}>
<Text style={{color:'#FFF'}}>
You are not connected to internet....!
</Text>
</View>
)
}
</View>
);
}
}
How can I get the network status without fetching every time when Network is lost and the Network is back again?
You have to add a listener to NetInfo.
Following code can help you,
const [networkState, setNetworkState] = useState(true);
const onNetworkStateChange = (newState) => {
setNetworkState(newState.isConnected);
if (!newState.isConnected) {
// do anything you want
}
};
const initialCheck = () =>
NetInfo.fetch().then((connectionInfo) => {
setNetworkState(connectionInfo.isConnected);
});
useEffect(() => {
initialCheck();
NetInfo.addEventListener(onNetworkStateChange);
}, []);
Related
I'm new to react-native, I'm making app which can connect to printer with bluetooth I'm using react-native-ble-plx . I had successfully connect to my printer with bluetooth but I don't know to to print some thing from it.
import React, {PureComponent} from 'react';
import {View, Text, Button} from 'react-native';
import {BleManager} from 'react-native-ble-plx';
export default class App extends PureComponent {
constructor(props) {
super(props);
this.state = {};
this.manager = new BleManager();
}
componentDidMount() {
const subscription = this.manager.onStateChange(state => {
if (state === 'PoweredOn') {
console.log(state);
this.scanAndConnect();
}
}, true);
}
scanAndConnect() {
this.manager.startDeviceScan(null, null, (error, device) => {
if (error) {
// Handle error (scanning will be stopped automatically)
console.log(error);
}
// if (device) {
// console.log(device);
// }
if (device.name === 'POSTEK061F') {
// Stop scanning as it's not necessary if you are scanning for one device.
this.manager.stopDeviceScan();
device
.connect()
.then(device => {
return device.discoverAllServicesAndCharacteristics();
})
.then(device => {
// Do work on device with services and characteristics
console.log(device.name);
console.log(device);
})
.catch(error => {
// Handle errors
});
// Proceed with connection.
}
});
}
async printHTML() {
//print something
}
render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Button onPress={this.printHTML} title="Print HTML" />
</View>
);
}
}
when user click on print button it should print some thing.
I'm using a component I wrote for one app, in a newer app. The code is like 99% identical between the first app, which is working, and the second app. Everything is fine except that debounce is not activating in the new app. What am I doing wrong?
// #flow
import type { Location } from "../redux/reducers/locationReducer";
import * as React from "react";
import { Text, TextInput, View, TouchableOpacity } from "react-native";
import { Input } from "react-native-elements";
import { GoogleMapsApiKey } from "../../.secrets";
import _, { debounce } from "lodash";
import { connect } from "react-redux";
import { setCurrentRegion } from "../redux/actions/locationActions";
export class AutoFillMapSearch extends React.Component<Props, State> {
textInput: ?TextInput;
state: State = {
address: "",
addressPredictions: [],
showPredictions: false
};
async handleAddressChange() {
console.log("handleAddressChange");
const url = `https://maps.googleapis.com/maps/api/place/autocomplete/json?key=${GoogleMapsApiKey}&input=${this.state.address}`;
try {
const result = await fetch(url);
const json = await result.json();
if (json.error_message) throw Error(json.error_message);
this.setState({
addressPredictions: json.predictions,
showPredictions: true
});
// debugger;
} catch (err) {
console.warn(err);
}
}
onChangeText = async (address: string) => {
await this.setState({ address });
console.log("onChangeText");
debounce(this.handleAddressChange.bind(this), 800); // console.log(debounce) confirms that the function is importing correctly.
};
render() {
const predictions = this.state.addressPredictions.map(prediction => (
<TouchableOpacity
style={styles.prediction}
key={prediction.id}
onPress={() => {
this.props.beforeOnPress();
this.onPredictionSelect(prediction);
}}
>
<Text style={text.prediction}>{prediction.description}</Text>
</TouchableOpacity>
));
return (
<View>
<TextInput
ref={ref => (this.textInput = ref)}
onChangeText={this.onChangeText}
value={this.state.address}
style={[styles.input, this.props.style]}
placeholder={"Search"}
autoCorrect={false}
clearButtonMode={"while-editing"}
onBlur={() => {
this.setState({ showPredictions: false });
}}
/>
{this.state.showPredictions && (
<View style={styles.predictionsContainer}>{predictions}</View>
)}
</View>
);
}
}
export default connect(
null,
{ setCurrentRegion }
)(AutoFillMapSearch);
I noticed that the difference in the code was that the older app called handleAddressChange as a second argument to setState. Flow was complaining about this in the new app so I thought async/awaiting setState would work the same way.
So changing it to this works fine (with no flow complaints for some reason. maybe because I've since installed flow-typed lodash. God I love flow-typed!):
onChangeText = async (address: string) => {
this.setState(
{ address },
_.debounce(this.handleAddressChange.bind(this), 800)
);
};
I installed the react-navigation package in react-native
I have implemented tab navigation and one of them is implemented in webview format.
My problem is that if I press the back physical button on Android, I go from the app itself to the previous tab, not back from the webview.
I've already applied the back button for the webview on the internet, but I have not done that.
I tried to display the onNavigationStateChange log when debugging, but it was not updated when url was moved after it was loaded at first startup. Here is the code I implemented:
import React from "react";
import {BackHandler} from "react-native";
import {WebView} from "react-native-webview";
class SermonScreen extends React.Component {
constructor(props) {
super(props);
}
static navigationOptions = {
header: null
};
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
_onNavigationStateChange(navState) {
console.log(navState);
this.setState({
canGoBack: navState.canGoBack
});
}
handleBackButton = () => {
console.log(this.state);
if (this.state.canGoBack === true) {
this.webView.goBack();
return true;
} else {
return false;
}
};
render() {
return (
<WebView
source={{uri: 'https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos' }}
ref={(webView) => this.webView = webView}
onNavigationStateChange={this._onNavigationStateChange.bind(this)}
/>
);
}
}
export default SermonScreen;
Following the official webview documnentation you could try to do this: https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#intercepting-hash-url-changes
In general you were almost there, however the way the YT navigation works made it impossible to be caught via the onNavigationStateChange, that's why we inject a JS code that intercepts these hash changes and posts a message to the parent component, we then catch it inside the onMessage handler and set the state variable properly. Copying the injectedJavaScript and onMessage properties to your example should solve your problem.
I prepared a component for you that seems to do what is needed:
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow
*/
import React, { Fragment } from "react";
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
BackHandler,
StatusBar
} from "react-native";
import { WebView } from "react-native-webview";
import {
Header,
LearnMoreLinks,
Colors,
DebugInstructions,
ReloadInstructions
} from "react-native/Libraries/NewAppScreen";
class App extends React.Component {
constructor(props) {
super(props);
this.startingUrl =
"https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos";
this.handleBackButton = this.handleBackButton.bind(this);
}
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.handleBackButton);
}
handleBackButton = () => {
console.log(this.state);
const { canGoBack } = this.state;
if (canGoBack) {
this.webView.goBack();
return true;
} else {
return false;
}
};
render() {
return (
<Fragment>
<WebView
source={{ uri: this.startingUrl }}
style={{ marginTop: 20 }}
ref={webView => (this.webView = webView)}
injectedJavaScript={`
(function() {
function wrap(fn) {
return function wrapper() {
var res = fn.apply(this, arguments);
window.ReactNativeWebView.postMessage('navigationStateChange');
return res;
}
}
history.pushState = wrap(history.pushState);
history.replaceState = wrap(history.replaceState);
window.addEventListener('popstate', function() {
window.ReactNativeWebView.postMessage('navigationStateChange');
});
})();
true;
`}
onMessage={({ nativeEvent: state }) => {
if (state.data === "navigationStateChange") {
// Navigation state updated, can check state.canGoBack, etc.
this.setState({
canGoBack: state.canGoBack
});
}
}}
/>
</Fragment>
);
}
}
export default App;
The response above was perfect. I set the state true for canGoBack though; I was getting a null error, so:
constructor(props) {
super(props);
this.startingUrl = "https://app.vethorcardpag.com.br/GIF/login/0/";
this.state = {
canGoBack : true
}
this.handleBackButton = this.handleBackButton.bind(this);
}
Here is a simple solution using the magic of React's State.
Hope this helps.
import React, { useRef, useState } from 'react'
export default function Component () {
// This is used to save the reference of your webview, so you can control it
const webViewRef = useRef(null);
// This state saves whether your WebView can go back
const [webViewcanGoBack, setWebViewcanGoBack] = useState(false);
const goBack = () => {
// Getting the webview reference
const webView = webViewRef.current
if (webViewcanGoBack)
// Do stuff here if your webview can go back
else
// Do stuff here if your webview can't go back
}
return (
<WebView
source={{ uri: `Your URL` }}
ref={webViewRef}
javaScriptEnabled={true}
onLoadProgress={({ nativeEvent }) => {
// This function is called everytime your web view loads a page
// and here we change the state of can go back
setWebViewcanGoBack(nativeEvent.canGoBack)
}}
/>
)
}
Original answer
https://stackoverflow.com/a/74500469/7823800
How to show React Native Homepage if is connected?
and if is not connected, Show a full screen photo? (with a Condition by NetInfo)
import React, {Component} from 'react';
import {
Platform,
StyleSheet,
Text,
View,
NetInfo
} from 'react-native';
function ConnectionOk() {
return (
<View >
<Text >
Welcome to React Native1!
</Text>
<Text >
To get started, edit App.js
</Text>
</View>
);
}
function ConnectionNotOk() {
return (
<View>
<Text>not Connected ...</Text>
</View>
);
}
type Props = {};
export default class App extends Component<Props> {
constructor(props) {
super(props)
this.state = {
isConnected: false,
isMounted: true
};
}
componentDidMount() {
// my way of checking internet, don't use both methods
// this.checkInternetConnection();
// Its good idea to attach event listener here, or in constructor
NetInfo.isConnected.addEventListener(
'connectionChange',
this.handleFirstConnectivityChange
);
};
componentWillUnmount() {
this.setState({
isMounted: false
});
// Its good idea to remove all event listener here
NetInfo.removeEventListener(
'connectionChange',
this.handleFirstConnectivityChange
);
};
checkInternetConnection() {
fetch("https://httpbin.org/ip")
.then(response => response.json())
.then(responseJson => {
//update the state only when component is mounted, else it will throw warning
if (this.state.isMounted) {
this.setState({
isConnected: true
});
}
}).catch(err => {
// No internet, redirect to some action if required
})
};
handleFirstConnectivityChange(isConnected) {
if (isConnected) {
this.setState({
isConnected: true
});
} else {
//redirect to some route if required
return <ConnectionNotOk />;
}
render() {
return this.state.isConnected ? < ConnectionOk /> : < ConnectionNotOk />
}
};
}
You can use some flag variable in component state.
From my experience I can say that NetInfo doesn't always gives correct info. ex Internet data is on but no internet connection, NetInfo will return true.
I handle this case by fetching some http api (say https://httpbin.org/ip) which is light and gives correct info about internet.
Also its a good idea to define,add/remove listeners in their appropriate places instead of render.
Try following:
type Props = {};
export default class App extends Component < Props > {
constructor(props) {
super(props)
this.state = {
isConnected: false,
isMounted: true
};
this.checkInternetConnection = this.checkInternetConnection.bind(this);
this.handleFirstConnectivityChange = this.handleFirstConnectivityChange.bind(this);
}
componentDidMount() {
// my way of checking internet, don't use both methods
// this.checkInternetConnection();
// Its good idea to attach event listener here, or in constructor
NetInfo.isConnected.addEventListener(
'connectionChange',
this.handleFirstConnectivityChange
);
}
componentWillUnmount() {
this.setState({
isMounted: false
});
// Its good idea to remove all event listener here
NetInfo.removeEventListener(
'connectionChange',
this.handleFirstConnectivityChange
);
}
checkInternetConnection() {
fetch("https://httpbin.org/ip")
.then(response => response.json())
.then(responseJson => {
//update the state only when component is mounted, else it will throw warning
if (this.state.isMounted) {
this.setState({
isConnected: true
});
}
}).catch(err => {
// No internet, redirect to some action if required
})
}
handleFirstConnectivityChange(isConnected) {
if (isConnected) {
this.setState({
isConnected: true
});
} else {
//redirect to some route if required
//return <ConnectedNotOk / > ;
}
}
render() {
return (
this.state.isConnected ? <ConnectionOk /> : <ConnectionNotOk />
);
}
}
My full example code.
NetInfo.isConnected.fetch().then(isConnected => {
console.log('First, is ' + (isConnected ? 'online' : 'offline'));
});
function handleFirstConnectivityChange(isConnected) {
console.log('Then, is ' + (isConnected ? 'online' : 'offline'));
if (isConnected == false) {
// your image
}
else{
Actions.HomePage() //if connected go to homepage
}
NetInfo.isConnected.removeEventListener(
'connectionChange',
handleFirstConnectivityChange
);
}
NetInfo.isConnected.addEventListener(
'connectionChange',
handleFirstConnectivityChange
);
i am using react-native-router-flux for redirection
You can achieve it by having isConnected flag in state and using network code set it to true or false dynamically. Then inside the render function use below code
{ this.state.isConnected &&
// Your UI code here
}
I have made some changes in your code. Hope it will help you. Please find complete code below:
import React, {Component} from 'react';
import {
Platform,
StyleSheet,
Text,
View,
NetInfo
} from 'react-native';
export default class App extends Component {
constructor(props) {
super(props)
this.state = {
isConnected: false,
isMounted: true
};
}
componentWillMount() {
NetInfo.addEventListener(
'connectionChange',
this.handleFirstConnectivityChange
);
}
componentWillUnmount() {
this.setState({
isMounted: false
});
// Its good idea to remove all event listener here
NetInfo.removeEventListener(
'connectionChange',
this.handleFirstConnectivityChange
);
}
handleFirstConnectivityChange(connectionInfo) {
if(connectionInfo.type && connectionInfo.type != "none"){
this.setState({
isConnected: true
});
}else {
this.setState({
isConnected: false
});
}
}
render () {
return (
<View>
{this.state.isConnected &&
<View >
<Text >
Welcome to React Native1!
</Text>
<Text >
To get started, edit App.js
</Text>
</View>
}
{!this.state.isConnected &&
<View>
<Text>not Connected ...</Text>
</View>
}
</View>
)
}
}
I want to send and receive data using facebook's suggestion
https://facebook.github.io/react-native/docs/network.html#websocket
but when I run the code it fails to import the "WebSocket" and app
crashes.
The code in the render method works just fine, but I do not want to
render a view again and again just to send data.
I want the code in componentWillMount function to run to send and
receive data. Please help me. I will be thankful to you.
import React, { Component } from 'react';
import WS from 'react-native-websocket';
import { View } from 'react-native';
export default class Example extends Component {
componentWillMount() {
const ws = new WebSocket('ws://host.com/path');
ws.onopen = () => {
// connection opened
ws.send('something'); // send a message
};
ws.onmessage = (e) => {
// a message was received
console.log(e.data);
};
ws.onerror = (e) => {
// an error occurred
console.log(e.message);
};
ws.onclose = (e) => {
// connection closed
console.log(e.code, e.reason);
};
}
render() {
return (
<View style={{ flex: 1 }}>
<WS
ref={ref => { this.ws = ref }}
url="http://34.206.187.250:1880/ws/praduman"
onOpen={() => {
console.log('Open!')
this.ws.send('Hello')
}}
onMessage={console.log}
onError={console.log}
onClose={console.log}
reconnect
/>
</View>
)
}
}
Try this:
import React, { Component } from 'react'
import { AppRegistry, View } from 'react-native'
import WS from 'react-native-websocket'
export default class Example extends Component {
_onOpen() {
console.log('Open!')
this.ws.send('Hello')
}
_onMessage(event) {
console.log('Data',event)
}
_onError(error) {
console.log('Error',error)
}
_onClose() {
console.log('Close!')
}
render () {
return (
<View style={{flex: 1}}>
<WS
ref={ref => {this.ws = ref}}
url="wss://echo.websocket.org/"
onOpen={() => this._onOpen.bind(this)}
onMessage={(event) => this._onMessage.bind(this)}
onError={(error) => this._onError.bind(this)}
onClose={() => this._onClose.bind(this)}
/>
</View>
)
}
}