I want to use WebSockets to send and receive data in REACT NATIVE - react-native

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

Related

Failed to start signInAsync as concurrent GoogleSignIn task

I have an app that I'm using to sign in into google with the expo-google-sign-in library. However, I'm getting the following error:
Error: Failed to start signInAsync as a concurrent GoogleSignIn task is already running
promiseMethodWrapper#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:2864:45
http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:100167:40
invokeAuthMethod$#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:157126:80
tryCatch#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:29230:23
invoke#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:29403:32
tryCatch#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:29230:23
invoke#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:29303:30
http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:29313:21
tryCallOne#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:4064:16
http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:4165:27
_callTimer#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:31253:17
_callImmediatesPass#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:31292:17
callImmediates#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:31509:33
__callImmediates#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:3358:35
http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:3144:34
__guard#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:3341:15
flushedQueue#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:3143:21
flushedQueue#[native code]
callFunctionReturnFlushedQueue#[native code]
Here's the code:
import * as React from 'react';
import { useEffect } from 'react';
import { StyleSheet, Image, Pressable, ImageBackground } from 'react-native';
import EditScreenInfo from '../components/EditScreenInfo';
import { Text, View } from '../components/Themed';
import * as GoogleSignIn from 'expo-google-sign-in';
export default function TabTwoScreen() {
// useEffect(async function () {
// try {
// console.log("running initAsync")
// await GoogleSignIn.initAsync({
// // You may ommit the clientId when the firebase `googleServicesFile` is configured
// clientId: '435403173197-1ofadf8gflla92ibd6ibveb4tvv1vice.apps.googleusercontent.com',
// // Provide other custom options...
// });
// } catch ({ message }) {
// alert('GoogleSignIn.initAsync(): ' + message);
// }
// }, []);
return (
<View style={styles.container}>
<ImageBackground source={require(
"../assets/images/happy-tiny-people-listening-spiritual-music/5870.jpg")}
style={styles.background}>
<Pressable onPress= {() => {
console.log("running sign in async");
GoogleSignIn.signInAsync();
}}
style={({ pressed }) => [{
backgroundColor: pressed ? 'white' : '#03befc'
},
styles.google]}>
<Image source={require("../assets/google_signin.png")} style={styles.googleImage}/>
<Text style={styles.googleText}>Sign In With Google</Text>
</Pressable>
</ImageBackground>
</View>
);
}
What am I doing wrong and how to fix this error? I expect there to be no error and that the google sign in to happen. The error occurs when the perusable is pressed.
This might help
const signInAsync = async () => {
try {
await GoogleSignIn.askForPlayServicesAsync();
const { type, user } = await GoogleSignIn.signInAsync();
if (type === 'success') {
// success
}
} catch ({ message }) {
alert('login: Error:' + message);
}
};
<Pressable onPress= {() => { signInAsync() }
More detail here sdk/google-sign-in/

Auto update Net Info status in react-native

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);
}, []);

React native Printer

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.

Lodash debounce not working all of a sudden?

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

react-native redux props changes back to undefined

I'm trying to add a filter to my app, but for some reason selectedValue in the <Picker> component doesn't stick with the option I select. I can see the filter text changing from "all" to "lobby" in the top left, however as soon as the player list fully renders, it changes back to "all." and playerListFilterType prop is set to undefined. I stepped through the code in a debugger, and it stays "lobby" until the list re-renders. The action itself works, so the list is showing accurate results.
Here's what my code looks like:
import React from 'react'
import { View, Picker } from 'react-native'
import PlayerList from '../components/PlayerList'
import { fetchPlayerListAsync, filterPlayers } from '../redux/actions/player_actions';
import NavigationHeaderTitle from '../components/NavigationHeaderTitle'
import PlayerStatusFilterPicker from '../components/pickers/PlayerStatusFilterPicker'
import { connect } from 'react-redux'
class PlayerListScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
const playerStatusFilterPicker = (
<PlayerStatusFilterPicker
playerListFilterType={navigation.getParam('playerListFilterType')}
filterPlayers={navigation.getParam('filterPlayers')}
playerList={navigation.getParam('playerList')}
/>
)
return {
headerTitle: navigation.getParam('headerButton'),
headerRight: playerStatusFilterPicker
}
}
async componentDidMount() {
await this.fetchPlayersAsync();
}
setNavigationParams = () => {
this.props.navigation.setParams({
headerButton: this.headerButton,
playerList: this.props.playerList,
playerListFilterType: this.props.playerListFilterType,
filterPlayers: this.props.filterPlayers
})
}
// navigation header element
headerButton = () => (
<NavigationHeaderTitle
handleDataRequest={this.fetchPlayersAsync}
titleMessage={(this.props.fetchingData) ? 'fetching list of players' : `${this.props.playerList.length} online`}
/>
)
fetchPlayersAsync = async () => {
await this.props.fetchPlayerListAsync();
this.setNavigationParams()
}
render() {
return (
<View>
<PlayerList
playerList={this.props.playerList}
fetchingData={this.props.fetchingData}
handleDataRequest={this.fetchPlayersAsync}
/>
</View>
)
}
}
const mapStateToProps = state => {
return {
fetchingData: state.player.fetchingData,
playerList: state.player.playerList,
unfilteredPlayerList: state.player.unfilteredPlayerList,
playerListFilterType: state.player.playerListFilterType
}
};
export default connect(mapStateToProps, { fetchPlayerListAsync, filterPlayers })(PlayerListScreen)
and here's what the filter component looks like, but I don't think the problem lies here:
import React, { Component } from "react";
import {
View,
Picker
} from "react-native";
import * as constants from '../../constants'
class PlayerStatusFilterPicker extends Component {
render() {
return (
<View>
<Picker
selectedValue={this.props.playerListFilterType}
onValueChange={(itemValue) => this.props.filterPlayers(itemValue, this.props.playerList)}
style={{ height: 40, width: 100 }}
>
<Picker.Item label='all' value='all' />
<Picker.Item label="lobby" value={constants.IN_LOBBY} />
<Picker.Item label="in game" value={constants.IN_GAME} />
</Picker>
</View>
);
}
}
export default PlayerStatusFilterPicker;
Here's what the reducer looks like:
// show only the players that are waiting in the main lobby
case actionTypes.SHOW_PLAYERS_IN_LOBBY: {
const filteredList = action.payload.filter(player => player.status === constants.IN_LOBBY)
return { playerList: filteredList, playerListFilterType: constants.IN_LOBBY, fetchingData: false }
}
// show only the players that are currently playing
case actionTypes.SHOW_PLAYERS_IN_GAME: {
const filteredList = action.payload.filter(player => player.status === constants.IN_GAME)
return { playerList: filteredList, playerListFilterType: constants.IN_LOBBY, fetchingData: false }
}
Fixed it by using componentDidUpdate lifecycle method. Like so:
componentDidUpdate(prevProps) {
if (this.props.playerListFilterType != prevProps.playerListFilterType) {
this.props.navigation.setParams({
playerListFilterType: this.props.playerListFilterType
})
}
}