Need to add avatar and username to post - reactjs

So, I'm trying to add the user avatar and username to my addPost. I've tried everything I can think of but nothing is working.
I've Tried;
firebase.auth().currentUser.avatar;
But that doesn't work, I'm assuming it's because "avatar" or "username" isn't firebase specific properties for auth.
I've also tried;
get uid() {
return firebase.auth().currentUser;
}
and then adding to addPost
avatar: this.uid.avatar,
username: this.uid.username
That doesn't work either.
I just need the user avatar and username to be available when called on the home screen.
import React from "react";
import { View, StyleSheet, FlatList, Platform, TouchableNativeFeedback, TouchableOpacity, Image, Button } from "react-native";
import Fire from '../../Fire';
import UsernameText from '../../components/Text/DefaultUsernameText';
import CreatedAtText from '../../components/Text/CreatedAtText';
import ThoughtTitleText from '../../components/Text/DefaultThoughtTitle';
import Colors from '../../constants/Colors';
import moment from 'moment';
let TouchableCmp = TouchableOpacity;
if (Platform.OS === 'android' && Platform.Version >= 21) {
TouchableCmp = TouchableNativeFeedback;
}
export default class HomeScreen extends React.Component {
state = {
latestPost: [],
}
displayLatestPost = (latestPost) => {
this.setState({latestPost: latestPost});
console.log("latest Post " + this.state.latestPost);
}
componentDidMount(){
Fire.shared.getPosts(this.displayLatestPost);
console.log("This is the displayLatestPost " + this.state.latestPost);
}
renderLatestPost = (post) => {
return (
<View>
<TouchableCmp onPress={() => {}} style={{flex: 1}}>
<View style={styles.container}>
<View style={styles.infoText}>
<Image style={styles.userAvatar}>{post.avatar}</Image>
<UsernameText style={styles.name} >{post.username}</UsernameText>
<CreatedAtText style={styles.timestamp}>{moment(post.timestamp).fromNow()}</CreatedAtText>
</View>
<View style={styles.container} >
<ThoughtTitleText style={styles.feedItem}>{post.thoughtTitle}</ThoughtTitleText>
</View>
</View>
</TouchableCmp>
</View>
);
};
render() {
return (
<View style={styles.container}>
<Button
onPress={() => {
Fire.shared.signOut();
}}
title="Log out"
/>
<FlatList
showsVerticalScrollIndicator={false}
keyExtractor={item => item.id}
style={styles.feed}
data={this.state.latestPost}
renderItem={( {item, index }) =>
this.renderLatestPost(item, index)
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.background
},
feed: {
marginHorizontal: 16
},
feedItem: {
borderRadius: 5,
padding: 2,
flexDirection: "row",
marginVertical: 2
},
name: {
fontSize: 15,
fontWeight: "500",
color: "#454D65"
},
timestamp: {
fontSize: 11,
color: "#C4C6CE",
marginTop: 4
},
post: {
marginTop: 16,
fontSize: 14,
color: "#838899"
},
postImage: {
width: undefined,
height: 150,
borderRadius: 5,
marginVertical: 16
},
container: {
flex:1,
borderRadius: 10,
padding:15,
justifyContent: 'flex-end',
alignItems: 'flex-end'
},
thought: {
color: '#666',
fontSize: 18,
marginBottom: 5,
alignItems: 'center'
},
infoText:{
flexDirection: "row"
},
// icons: {
// flexDirection: 'row'
// },
userAvatar: {
backgroundColor: Colors.subheadings,
borderColor: Colors.accent,
borderWidth:3.5,
backgroundColor: Colors.maintext,
marginEnd: 15,
width: 35,
height: 35,
borderRadius: 20,
}
});
Here's my Fire.js
import FirebaseKeys from "./config/FirebaseKeys";
import firebase from "firebase/app";
import '#firebase/auth';
import 'firebase/database';
import '#firebase/firestore';
import "firebase/storage";
require("firebase/firestore");
class Fire {
constructor() {
firebase.initializeApp(FirebaseKeys);
}
getPosts = async (displayLatestPost) => {
const post = await
this.firestore.collection('thoughts').orderBy('timestamp', ' desc').limit(10).get()
let postArray =[]
post.forEach((post) => {
postArray.push({id: post.id, ...post.data()})
})
displayLatestPost(postArray)
}
addPost = async ({ thoughtTitle, thoughtText, localUri, avatar, username}) => {
const remoteUri = await this.uploadPhotoAsync(localUri, `photos/${this.uid}/${Date.now()}`);
return new Promise((res, rej) => {
this.firestore
.collection("thoughts")
.add({
uid: this.uid,
thoughtTitle,
thoughtText,
image: remoteUri,
timestamp: this.timestamp,
})
.then(ref => {
res(ref);
})
.catch(error => {
rej(error);
});
});
};
uploadPhotoAsync = (uri, filename) => {
return new Promise(async (res, rej) => {
const response = await fetch(uri);
const file = await response.blob();
let upload = firebase
.storage()
.ref(filename)
.put(file);
upload.on(
"state_changed",
snapshot => {},
err => {
rej(err);
},
async () => {
const url = await upload.snapshot.ref.getDownloadURL();
res(url);
}
);
});
};
createUser = async user => {
let remoteUri = null;
try {
await firebase.auth().createUserWithEmailAndPassword(user.email, user.password);
let db = this.firestore.collection("users").doc(this.uid);
db.set({
username: user.username,
email: user.email,
avatar: null
});
if (user.avatar) {
remoteUri = await this.uploadPhotoAsync(user.avatar, `avatars/${this.uid}`);
db.set({ avatar: remoteUri }, { merge: true });
}
} catch (error) {
alert("Error: ", error);
}
};
updateProfile = async user => {
let remoteUri = null;
try {
let db =
this.firestore.collection("users").doc(this.uid);
db.update({
username: user.username,
email: user.email,
avatar: null
});
if (user.avatar) {
remoteUri = await this.uploadPhotoAsync(user.avatar, `avatars/${this.uid}`);
db.set({ avatar: remoteUri }, { merge: true });
}
} catch (error) {
alert("Error: ", error);
}
}
signOut = () => {
firebase.auth().signOut();
};
get firestore() {
return firebase.firestore();
}
/* get username(){
return firebase.auth().currentUser.username;
} */
get uid() {
return (firebase.auth().currentUser || {}).uid;
}
/* get avatar(){
return firebase.auth().currentUser.avatar;
} */
get timestamp() {
return Date.now();
}
}
Fire.shared = new Fire();
export default Fire;

I hope the following information helps.
You can store Name & Profile Picture URL like this:
var user = firebase.auth().currentUser;
// Update User Profile
user.updateProfile({
displayName: "Jane Doe",
photoURL: "https://example.com/1hdfabSesfE/profile.jpg"
}).then(function() {
// Update successful.
}).catch(function(error) {
// An error happened.
});
// Use these parameters inside the add post function
var profilePicture = user.photoURL;
var name = user.displayName;

So, I changed my createUser and updateUser
createUser = async user => {
let remoteUri = null;
try {
await firebase.auth().createUserWithEmailAndPassword(user.email, user.password);
let db = this.firestore.collection("users").doc(this.uid);
db.set({
displayName: user.displayName,
email: user.email,
photoURL: null
});
if (user.photoURL) {
remoteUri = await this.uploadPhotoAsync(user.photoURL, `avatars/${this.uid}`);
db.set({ photoURL: remoteUri }, { merge: true });
}
} catch (error) {
alert("Error: ", error);
}
};
updateProfile = async user => {
let remoteUri = null;
try {
let db = this.firestore.collection("users").doc(this.uid);
db.update({
displayName: user.displayName,
photoURL: user.photoURL
});
if (user.photoURL) {
remoteUri = await this.uploadPhotoAsync(user.photoURL, `avatars/${this.uid}`);
db.set({ photoURL: remoteUri }, { merge: true });
}
} catch (error) {
alert("Error: ", error);
}
}
Then I changed my addPost
addPost = async ({ thoughtTitle, thoughtText, localUri, photoURL, displayName}) => {
const remoteUri = await this.uploadPhotoAsync(localUri, `photos/${this.uid}/${Date.now()}`);
return new Promise((res, rej) => {
this.firestore
.collection("thoughts")
.add({
uid: this.uid,
displayName,
photoURL,
thoughtTitle,
thoughtText,
image: remoteUri,
timestamp: this.timestamp,
})
.then(ref => {
res(ref);
})
.catch(error => {
rej(error);
});
});
};
Thanks for all the help - It's working!.
Here's my account screen where I update the displayName and photoURL
import React from "react";
import { View, Text, StyleSheet, Button, Image, TextInput, TouchableOpacity} from
"react-native";
import Fire from "../../Fire";
import { MaterialIcons } from "#expo/vector-icons"
import * as ImagePicker from "expo-image-picker";
import UserPermissions from "../../utilities/UserPermissions";
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
//import Avatar from '../../components/User/Avatar';
export default class AccountScreen extends React.Component {
state = {
user: {},
updatedUser: {
photoURL: null,
displayName: ""
}
};
unsubscribe = null;
componentDidMount() {
const user = this.props.uid || Fire.shared.uid;
this.unsubscribe = Fire.shared.firestore
.collection("users")
.doc(user)
.onSnapshot(doc => {
this.setState({ user: doc.data() });
});
}
componentWillUnmount() {
this.unsubscribe();
}
handleUpdate = () => {
Fire.shared.updateProfile(this.state.updatedUser);
};
handlePickAvatar = async () => {
UserPermissions.getCameraPermission();
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 0.1
});
if (!result.cancelled) {
this.setState({ updatedUser: { ...this.state.updatedUser, photoURL: result.uri
} });
}
};
render() {
return (
<View style={styles.container}>
<KeyboardAwareScrollView
style={{ flex: 1, width: '100%' }}
keyboardShouldPersistTaps="always">
<View style={styles.container}>
<TouchableOpacity style={styles.avatarContainer} onPress=.
{this.handlePickAvatar}>
<Image
source={
this.state.updatedUser.photoURL
? { uri: this.state.user.photoURL }
: require("../../assets/tempAvatar.jpg")
}
style={styles.avatar}
/>
<MaterialIcons
name="photo-camera"
size={40} color="grey"
style={{ marginTop: 6, marginLeft: 2 }}
/>
</TouchableOpacity>
<View>
<TextInput
style={styles.border}
placeholder= "change username"
onChangeText={displayName => this.setState({ updatedUser: { ...this.state.updatedUser, displayName } })}
value={this.state.updatedUser.displayName}
></TextInput>
</View>
<TouchableOpacity onPress={this.handleUpdate}>
<MaterialIcons name="check" size={24} color="black" />
</TouchableOpacity>
</View>
</KeyboardAwareScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
},
profile: {
marginTop: 64,
alignItems: "center"
},
avatarContainer: {
shadowColor: "#151734",
shadowRadius: 30,
shadowOpacity: 0.4
},
avatar: {
width: 100,
height: 100,
borderRadius: 68
},
name: {
marginTop: 24,
fontSize: 16,
fontWeight: "600"
},
statsContainer: {
flexDirection: "row",
justifyContent: "space-between",
margin: 32
},
stat: {
alignItems: "center",
flex: 1
},
statAmount: {
color: "#4F566D",
fontSize: 18,
fontWeight: "300"
},
statTitle: {
color: "#C3C5CD",
fontSize: 12,
fontWeight: "500",
marginTop: 4
},
border: {
width: 200,
margin: 10,
padding: 15,
fontSize: 16,
borderColor: '#d3d3d3',
borderBottomWidth: 1,
textAlign: 'center'
},
});
Here's my Home.js
import React from "react";
import { View, StyleSheet, FlatList, Platform,
TouchableNativeFeedback,
TouchableOpacity, Image, Button } from "react-native";
import Fire from '../../Fire';
import UsernameText from '
../../components/Text/DefaultUsernameText';
import CreatedAtText from '../../components/Text/CreatedAtText';
import ThoughtTitleText from '
../../components/Text/DefaultThoughtTitle';
import Colors from '../../constants/Colors';
import moment from 'moment';
let TouchableCmp = TouchableOpacity;
if (Platform.OS === 'android' && Platform.Version >= 21) {
TouchableCmp = TouchableNativeFeedback;
}
export default class HomeScreen extends React.Component {
state = {
latestPost: [],
}
displayLatestPost = (latestPost) => {
this.setState({latestPost: latestPost});
console.log("latest Post " + this.state.latestPost);
}
componentDidMount(){
Fire.shared.getPosts(this.displayLatestPost);
console.log("This is the displayLatestPost " + this.state.latestPost);
}
renderLatestPost = (post) => {
return (
<View>
<TouchableCmp onPress={() => {}} style={{flex: 1}}>
<View style={styles.container}>
<View style={styles.infoText}>
<Image style={styles.userAvatar} source={{uri:
post.photoURL}} />
<UsernameText style={styles.name} >{post.displayName}.
</UsernameText>
<CreatedAtText style={styles.timestamp}>.
{moment(post.timestamp).fromNow()}</CreatedAtText>
</View>
<View style={styles.container} >
<ThoughtTitleText style={styles.feedItem}>{post.thoughtTitle}.
</ThoughtTitleText>
</View>
</View>
</TouchableCmp>
</View>
);
};
render() {
return (
<View style={styles.container}>
<Button
onPress={() => {
Fire.shared.signOut();
}}
title="Log out"
/>
<FlatList
showsVerticalScrollIndicator={false}
keyExtractor={item => item.id}
style={styles.feed}
data={this.state.latestPost}
renderItem={( {item, index }) =>
this.renderLatestPost(item, index)
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.background
},
feed: {
marginHorizontal: 16
},
feedItem: {
borderRadius: 5,
padding: 2,
flexDirection: "row",
marginVertical: 2
},
name: {
fontSize: 15,
fontWeight: "500",
color: "#454D65"
},
timestamp: {
fontSize: 11,
color: "#C4C6CE",
marginTop: 4
},
post: {
marginTop: 16,
fontSize: 14,
color: "#838899"
},
postImage: {
width: undefined,
height: 150,
borderRadius: 5,
marginVertical: 16
},
container: {
flex:1,
borderRadius: 10,
padding:15,
justifyContent: 'flex-end',
alignItems: 'flex-end'
},
thought: {
color: '#666',
fontSize: 18,
marginBottom: 5,
alignItems: 'center'
},
infoText:{
flexDirection: "row"
},
// icons: {
// flexDirection: 'row'
// },
userAvatar: {
backgroundColor: Colors.subheadings,
borderColor: Colors.accent,
borderWidth:3.5,
backgroundColor: Colors.maintext,
marginEnd: 15,
width: 35,
height: 35,
borderRadius: 20,
}
});

Related

Huge State Array with number of Inputs, reduce performance when state changes [React-native]

I'm working on an app which the users will enter large number of records continuously. App functionalities are completed but the performance is slow . As i'm new to react native I've not much idea on this. But when I googled regarding this issue it has been noticed that when the state changes the whole app get rerenders. So as per some blogs they suggested to split components into pieces i.e., parent and child. I've done that but also the performance is low. Also they suggested to memorize the state and components. But I didn't understand what they meant.
This was my previous code before i split into components Previous code and this is my existing code after i splitted this into components.
import React, { useState, useEffect, useRef } from 'react'
import { StyleSheet, View, ScrollView, Text, RefreshControl, Alert } from 'react-native'
import Background from '../components/Background'
import Header from '../components/Header'
import { Appbar, Button, DataTable, ActivityIndicator, Menu, Divider, IconButton } from 'react-native-paper'
import{ showMessage } from "react-native-flash-message";
import { theme } from '../core/theme'
import Icon from 'react-native-vector-icons/Ionicons';
import { numberValidator } from '../helpers/numberValidator'
import AsyncStorage from '#react-native-async-storage/async-storage';
import * as constants from "../core/constants";
import axios from "axios";
import NumberInput from '../components/NumberInput'
import moment from 'moment';
const Componentinput = ({data,setListData,scrollref}) => {
const ref = React.useRef(View.prototype);
const firstref = React.useRef(View.prototype);
const [digit, setDigit] = useState({ value: '', error: '' })
const [count, setCount] = useState({ value: '', error: '' })
const onSubmitPress = async () => {
const digitError = numberValidator(digit.value)
const countError = numberValidator(count.value)
const usertoken = await AsyncStorage.getItem("#userToken")
if (digitError || countError) {
setDigit({ ...digit, error: digitError })
setCount({ ...count, error: countError })
return
}else if(digit.value.length < 3 || digit.value.length > 3){
setDigit({ ...digit, error: 'Enter 3 digits' })
return
}
let date = moment().format('YYYY-MM-DD HH:mm:ss');
axios
.post(
constants.BASE_URL+'savedata',
{
digit: digit.value,
count:count.value,
created_at:date,
token: usertoken
},
{
headers: {
"Content-Type": "application/json"
}
}
)
.then(setListData([...data, {digit:digit.value, count:count.value, countsum:'', created_at:date}]))
.then(firstref.current.focus(),scrollref.current.scrollToEnd({animated: true}))
// .then(firstref.current.focus())
.then(setDigit({ value: '', error: '' }),setCount({ value: '', error: '' }))
.then(response => {
if(response.data.status == 1){
setListData(response.data.data);
}
})
.catch(error => {
// setLoading(false)
showMessage({
message: "Error Occured",
description: "Oops!! Please try again",
type: "danger",
color: "#fff",
icon: "danger",
floating: true,
});
});
}
return (
<View style={styles.fixedform}>
<View style={styles.textinputViewleft}>
<NumberInput
style={styles.textinput}
ref={firstref}
label="Digit"
returnKeyType="next"
value={digit.value}
onChangeText={(text) => { setDigit({ value: text, error: '' }); if (text.length === 3) { ref.current.focus(); } }}
error={!!digit.error}
errorText={digit.error}
keyboardType="numeric"
maxLength={3}
minLength={3}/>
</View>
<View style={styles.textinputView}>
<NumberInput
style={styles.textinput}
ref={ref}
label="Count"
value={count.value}
onChangeText={(text) => setCount({ value: text, error: '' })}
error={!!count.error}
errorText={count.error}
keyboardType="numeric"
maxLength={3}/>
</View>
<View style={styles.textinputView}>
<Button style={styles.buttonView} mode="contained" onPress={onSubmitPress} >Submit</Button>
</View>
</View>
)
}
const Dashboard = ({ navigation }) => {
const [listdata, setListData] = useState([])
const [menuvisible, setMenuVisible] = useState(false);
const [refreshing, setRefreshing] = useState(false);
const scrollViewRef = useRef();
const [exceedCnt, setexceedCnt] = useState(null)
useEffect(() => {
async function fetchData() {
setexceedCnt(await AsyncStorage.getItem("#exceedCount"))
}
fetchData();
getListData();
}, []);
const openMenu = () => setMenuVisible(true);
const closeMenu = () => setMenuVisible(false);
const onRefresh = () => {
setRefreshing(true);
getListData();
};
const logOut = async () => {
setMenuVisible(false);
try {
await AsyncStorage.clear()
navigation.reset({
index: 0,
routes: [{ name: 'LoginScreen' }],
})
console.log('Storage successfully cleared!')
} catch (e) {
console.log('Failed to clear the async storage.')
}
}
const getListData = async () => {
const token = await AsyncStorage.getItem("#userToken")
try {
axios
.get(constants.BASE_URL + "getlist?token=" +token)
.then(response => {
setRefreshing(false)
setListData(response.data)
})
.catch(error => {
console.log(error);
});
} catch(error) {
console.log(error);
}
}
const deleteConfirmation = (index,id) => {
Alert.alert(
"Warning",
"Do you want to delete this record?",
[
{
text: "Cancel",
onPress: () => console.log("Cancel Pressed"),
style: "cancel"
},
{ text: "OK", onPress: () => onDeletePress(index,id) }
],
{ cancelable: true }
);
}
const onDeletePress = async (index,id) => {
const usertoken = await AsyncStorage.getItem("#userToken")
try {
axios.post(constants.BASE_URL+'deletedata',
{
id: id,
token: usertoken
},
{
headers: {
"Content-Type": "application/json"
}
}
)
.then(response => {
if(response.data.status == 1){
showMessage({
message: "Success",
description: "Data Deleted successfully",
type: "success",
color: "#fff",
icon: "success",
floating: true
});
var array = [...listdata]; // make a separate copy of the array
if (index !== -1) {
array.splice(index, 1);
setListData(response.data.data);
}
}else{
showMessage({
message: "Error Occured",
description: "Oops!! Please try again",
type: "danger",
color: "#fff",
icon: "danger",
floating: true,
});
}
})
.catch(error => {
showMessage({
message: "Error Occured",
description: "Oops!! Please try again",
type: "danger",
color: "#fff",
icon: "danger",
floating: true,
});
});
} catch(error) {
console.log(error);
}
}
const onDeleteoldrecordsPress = async () => {
setMenuVisible(false)
const usertoken = await AsyncStorage.getItem("#userToken")
try {
axios.post(constants.BASE_URL+'deletepreviousdata',
{
token: usertoken
},
{
headers: {
"Content-Type": "application/json"
}
}
)
.then(response => {
if(response.data.status == 1){
// setUploadData([]);
showMessage({
message: "Success",
description: "Data Deleted successfully",
type: "success",
color: "#fff",
icon: "success",
floating: true
});
getListData();
}else{
showMessage({
message: "Error Occured",
description: "Oops!! Please try again",
type: "danger",
color: "#fff",
icon: "danger",
floating: true,
});
}
})
.catch(error => {
showMessage({
message: "Error Occured",
description: "Oops!! Please try again",
type: "danger",
color: "#fff",
icon: "danger",
floating: true,
});
});
} catch(error) {
console.log(error);
}
}
const setexceedCount = () => {
setMenuVisible(false);
navigation.navigate('SetCountScreen');
}
const onDetailsPress = async () => {
navigation.reset({
routes: [{ name: 'DetailsScreen' }],
})
}
return (
<Background>
<Appbar style={styles.top}>
<Menu style={styles.menu}
visible={menuvisible}
onDismiss={closeMenu}
anchor={<Button onPress={openMenu}><Icon style={styles.appbariconfloat} name="ellipsis-vertical-outline" type="ionicon"/></Button>}>
<Menu.Item icon="trash-can-outline" onPress={onDeleteoldrecordsPress} title="Delete old records" />
<Divider />
<Menu.Item icon="plus" onPress={setexceedCount} title="Set Count" />
<Divider />
<Menu.Item icon="power" onPress={logOut} title="Logout" />
</Menu>
<Appbar.Content title='Add records' />
<Appbar.Action icon="table" onPress={onDetailsPress} />
</Appbar>
<Header style={styles.headermargin}></Header>
<View style={styles.datatable}>
{/* <ActivityIndicator style={styles.loadercenter} animating={loading} color="white" /> */}
<DataTable>
<DataTable.Header>
<DataTable.Title>Digit</DataTable.Title>
<DataTable.Title>Count</DataTable.Title>
<DataTable.Title>Total</DataTable.Title>
<DataTable.Title numeric>Action</DataTable.Title>
</DataTable.Header>
{listdata.length > 0 ?
<ScrollView ref={scrollViewRef} style={{marginBottom:150}} refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}>
{listdata.map((item, index) => {
return (
<DataTable.Row key={index}>
<DataTable.Cell > {item.digit} </DataTable.Cell>
<DataTable.Cell > {item.count} </DataTable.Cell>
<DataTable.Cell > <Text style={ (parseInt(item.countsum) > exceedCnt) ? styles.countstyleexceed : styles.countstylenotexceed}>{item.countsum}</Text> </DataTable.Cell>
<DataTable.Cell numeric>
<IconButton icon="delete" color="red" size={20} onPress={() => deleteConfirmation(index,item.id)} />
</DataTable.Cell>
</DataTable.Row>
)
})}
<DataTable.Row>
</DataTable.Row>
</ScrollView>
: console.log('no records found')}
{listdata.length == 0
?<DataTable.Row style={styles.norecords}><Text style={{color:"white"}}>No Records found</Text></DataTable.Row>
: console.log("records found")
}
</DataTable>
</View>
<Componentinput
data={listdata}
setListData={setListData}
scrollref={scrollViewRef}
/>
</Background>
)
}
export default Dashboard
const styles = StyleSheet.create({
top: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
},
headermargin: {
marginTop: 40,
},
customView: {
width: '100%',
marginTop: 37
},
appbariconfloat:{
// marginLeft: 0,
// left:0
color:"white",
fontSize:20
},
datatable:{
backgroundColor:'white',
width:'100%',
// marginBottom: 200,
// minHeight:10
},
textinputView:{
flex: 1,
marginRight: 10
},
textinputViewleft:{
flex: 1,
marginRight: 10,
marginLeft: 10
},
textinput:{
height: 55,
margin: 0,
backgroundColor:"#272727",
borderWidth:0.3,
borderColor:"#dfdfdf",
borderRadius: 4
},
buttonView:{
height: 55,
justifyContent: 'center',
marginTop: 12
},
fixedform:{
flexDirection: 'row',
width:'auto',
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
backgroundColor: '#272727',
},
datatable:{
backgroundColor:'#272727',
width:'100%',
marginBottom: 82
},
iconstyle:{
color: 'red',
},
loader:{
color:"white",
},
loadercenter:{
position:"absolute",
left:0,
right:0,
top:0,
bottom:0
},
menu:{
paddingTop: 20,
flexDirection: 'row',
// justifyContent: 'left',
left:8
},
norecords:{
marginTop:25,
},
countstyleexceed:{
color:"red",
fontWeight:"bold"
},
countstylenotexceed:{
color:'#00ff69',
fontWeight:'bold'
}
})

Issue with messages rendering a view specific to onLongPress

I am trying to render a View through renderCustomView={this.displayEmojis} for an individual message once a user has activated the onLongPress={} function. However, the view im trying to display repeats for every single message on the screen, rather than the one pressed. I have attached what happens when I try to press on a message with multiple messages showing:
//EventPost
import React from 'react'
import { Platform, View, StatusBar, TouchableOpacity, Text, Image, StyleSheet } from 'react-native'
import { getStatusBarHeight } from 'react-native-status-bar-height';
import { GiftedChat } from 'react-native-gifted-chat'
import emojiUtils from 'emoji-utils'
import KeyboardSpacer from 'react-native-keyboard-spacer';
import SlackMessage from './SlackMessage'
import Keyboard from 'react-native';
export default class EventPosts extends React.Component {
constructor(props) {
super(props);
this.state = {
messages: [],
toggle: false,
reactedMessage: 0,
reacted: false,
images: [
require("../assets/emojis/beer_photo.png"),
require("../assets/emojis/party_photo.png"),
require("../assets/emojis/laughing-emoji_photo.png"),
require("../assets/emojis/happy_photo.png"),
require("../assets/emojis/crying_photo.png"),
],
id: 0,
}
this.displayEmojis = this.displayEmojis.bind(this);
}
componentDidMount() {
this.setState({
messages: [
{
_id: 1,
text: 'I cant wait for this birthday party',
createdAt: new Date(),
user: {
_id: 2,
name: 'Andrew Garrett',
avatar: 'https://placeimg.com/140/140/any',
},
},
],
});
}
onSend(messages = []) {
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, messages),
}))
}
renderMessage(props) {
const {
currentMessage: { text: currText },
} = props
let messageTextStyle
if (currText && emojiUtils.isPureEmojiString(currText)) {
messageTextStyle = {
fontSize: 28,
lineHeight: Platform.OS === 'android' ? 34 : 30,
}
}
return (<SlackMessage {...props} messageTextStyle={messageTextStyle} />)
}
dismiss = () =>
Keyboard.dismiss();
updateEmojiCount(number) {
switch (number) {
case 1:
this.setState({ reactedMessage: 0 });
break;
case 2:
this.setState({ reactedMessage: 1 });
break;
case 3:
this.setState({ reactedMessage: 2 });
break;
case 4:
this.setState({ reactedMessage: 3 });
break;
case 5:
this.setState({ reactedMessage: 4 });
break;
default:
this.forceUpdate();
}
this.setState({ reacted: true });
this.setState({ toggle: false })
}
beerEmoji() {
return (
<View>
<TouchableOpacity style={styles.emojiContainer}
onPress={() => this.updateEmojiCount(1)}>
<Image style={styles.emoji} source={require("../assets/emojis/beer.gif")} />
</TouchableOpacity>
</View>
)
}
partyEmoji() {
return (
<View>
<TouchableOpacity style={styles.emojiContainer}
onPress={() => this.updateEmojiCount(2)}>
<Image style={styles.emoji} source={require("../assets/emojis/party.gif")} />
</TouchableOpacity>
</View>
)
}
laughingEmoji() {
return (
<View>
<TouchableOpacity onPress={() => this.updateEmojiCount(3)} style={styles.emojiContainer}>
<Image style={[styles.emoji, styles.emojiResize]} source={require("../assets/emojis/laughing-emoji.gif")} />
</TouchableOpacity>
</View>
)
}
happyEmoji() {
return (
<View>
<TouchableOpacity onPress={() => this.updateEmojiCount(4)} style={styles.emojiContainer}>
<Image style={[styles.emoji, styles.emojiResize]} source={require("../assets/emojis/happy.gif")} />
</TouchableOpacity>
</View>
)
}
cryingEmoji() {
return (
<View>
<TouchableOpacity onPress={() => this.updateEmojiCount(5)} style={styles.emojiContainer}>
<Image style={[styles.emoji, styles.emojiResize]} source={require("../assets/emojis/crying.gif")} />
</TouchableOpacity>
</View>
)
}
displayEmojis() {
if (this.state.toggle) {
return (
<View
style={{
flexDirection: 'row',
right: '35%',
backgroundColor: 'white',
zIndex: 3,
overlayColor: 'white',
borderRadius: 30,
paddingHorizontal: '10%',
bottom: '2%'
}}>
{this.beerEmoji()}
{this.partyEmoji()}
{this.laughingEmoji()}
{this.happyEmoji()}
{this.cryingEmoji()}
</View>
)
}
}
toggleEmojis = (context, message) => {
let temp = this.state.messages.filter(temp => message._id == temp._id);
let id = temp[0]._id;
this.setState({ id: temp[0]._id })
if (this.state.toggle) { this.setState({ toggle: false }) }
else { this.setState({ toggle: true }) }
}
render() {
return (
<View style={{ flex: 1 }}>
<View
style={{ paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : getStatusBarHeight() }}>
<View style={{ backgroundColor: '#2c3e50', paddingVertical: '4%' }}>
<TouchableOpacity style={{ left: "89%", top: '0%' }} onPress={() => this.props.navigation.goBack()}>
<Text style={{ color: 'white' }}>Done</Text>
</TouchableOpacity>
</View>
</View>
<GiftedChat
keyboardShouldPersistTaps={'handled'}
messages={this.state.messages}
onSend={messages => this.onSend(messages)}
placeholder={"Post something..."}
isKeyboardInternallyHandled={false}
multiline={true}
extraData={this.state}
alwaysShowSend={true}
onLongPress={this.toggleEmojis}
user={{ _id: 1 }}
renderCustomView={this.displayEmojis}
renderMessage={this.renderMessage} />
<KeyboardSpacer />
</View>
)
}
}
const styles = StyleSheet.create({
emojiContainer: {
width: 55,
height: 55,
paddingHorizontal: '13%',
right: '15%'
},
emoji: {
width: 55,
height: 55,
borderRadius: 20,
},
emojiResize: {
transform: [{ scale: 0.75 }],
},
emojiReacted: {
transform: [{ scale: 0.4 }],
},
})
//SlackMessage
import PropTypes from 'prop-types';
import React from 'react';
import {
View,
ViewPropTypes,
StyleSheet,
Image
} from 'react-native';
import { Avatar, Day, utils } from 'react-native-gifted-chat';
import Bubble from './SlackBubble';
const { isSameUser, isSameDay } = utils;
export default class Message extends React.Component {
state = {
images: [
require("../assets/emojis/beer_photo.png"),
require("../assets/emojis/party_photo.png"),
require("../assets/emojis/laughing-emoji_photo.png"),
require("../assets/emojis/happy_photo.png"),
require("../assets/emojis/crying_photo.png"),
]
}
getInnerComponentProps() {
const { containerStyle, ...props } = this.props;
return {
...props,
position: 'left',
isSameUser,
isSameDay,
};
}
renderDay() {
if (this.props.currentMessage.createdAt) {
const dayProps = this.getInnerComponentProps();
if (this.props.renderDay) {
return this.props.renderDay(dayProps);
}
return <Day {...dayProps} />;
}
return null;
}
renderBubble() {
const bubbleProps = this.getInnerComponentProps();
if (this.props.renderBubble) {
return this.props.renderBubble(bubbleProps);
}
return <Bubble {...bubbleProps} />;
}
renderAvatar() {
let extraStyle;
if (
isSameUser(this.props.currentMessage, this.props.previousMessage)
&& isSameDay(this.props.currentMessage, this.props.previousMessage)
) {
extraStyle = { height: 0 };
}
const avatarProps = this.getInnerComponentProps();
return (
<Avatar
{...avatarProps}
imageStyle={{ left: [styles.slackAvatar, avatarProps.imageStyle, extraStyle] }}
/>
);
}
render() {
const marginBottom = isSameUser(this.props.currentMessage, this.props.nextMessage) ? 2 : 10;
const { images } = this.state
const index = (this.props.extraData.reactedMessage);
return (
<View>
{this.renderDay()}
<View
style={[
styles.container,
{ marginBottom },
this.props.containerStyle,
]}>
{this.renderAvatar()}
{this.renderBubble()}
{<Image source={images[index]} style={{ width: 20, height: 20, right: '8%' }} />}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'flex-end',
justifyContent: 'flex-start',
marginLeft: 8,
marginRight: 8,
backgroundColor: 'white',
borderWidth: 2,
borderColor: '#BEBEBE',
paddingBottom: '3%'
},
slackAvatar: {
height: 40,
width: 40,
borderRadius: 3,
left: '10%',
bottom: '12%'
},
});
Message.defaultProps = {
renderAvatar: undefined,
renderBubble: null,
renderDay: null,
currentMessage: {},
nextMessage: {},
previousMessage: {},
user: {},
containerStyle: {},
};
Message.propTypes = {
renderAvatar: PropTypes.func,
renderBubble: PropTypes.func,
renderDay: PropTypes.func,
currentMessage: PropTypes.object,
nextMessage: PropTypes.object,
previousMessage: PropTypes.object,
user: PropTypes.object,
containerStyle: PropTypes.shape({
left: ViewPropTypes.style,
right: ViewPropTypes.style,
}),
};
//Bubble
import PropTypes from 'prop-types';
import React from 'react';
import {
Text,
Clipboard,
StyleSheet,
TouchableOpacity,
View,
ViewPropTypes,
Platform,
} from 'react-native';
import { MessageText, MessageImage, Time, utils } from 'react-native-gifted-chat';
const { isSameUser, isSameDay } = utils;
export default class Bubble extends React.Component {
constructor(props) {
super(props);
this.onLongPress = this.onLongPress.bind(this);
}
onLongPress() {
if (this.props.onLongPress) {
this.props.onLongPress(this.context, this.props.currentMessage);
} else {
if (this.props.currentMessage.text) {
const options = [
'Copy Text',
];
const cancelButtonIndex = options.length - 1;
this.context.actionSheet().showActionSheetWithOptions({
options,
cancelButtonIndex,
},
(buttonIndex) => {
switch (buttonIndex) {
case 0:
Clipboard.setString(this.props.currentMessage.text);
break;
}
});
}
}
}
renderMessageText() {
if (this.props.currentMessage.text) {
const { containerStyle, wrapperStyle, messageTextStyle, ...messageTextProps } = this.props;
if (this.props.renderMessageText) {
return this.props.renderMessageText(messageTextProps);
}
return (
<MessageText
{...messageTextProps}
textStyle={{
left: [styles.standardFont, styles.slackMessageText, messageTextProps.textStyle, messageTextStyle],
}}
/>
);
}
return null;
}
renderMessageImage() {
if (this.props.currentMessage.image) {
const { containerStyle, wrapperStyle, ...messageImageProps } = this.props;
if (this.props.renderMessageImage) {
return this.props.renderMessageImage(messageImageProps);
}
return <MessageImage {...messageImageProps} imageStyle={[styles.slackImage, messageImageProps.imageStyle]} />;
}
return null;
}
renderTicks() {
const { currentMessage } = this.props;
if (this.props.renderTicks) {
return this.props.renderTicks(currentMessage);
}
if (currentMessage.user._id !== this.props.user._id) {
return null;
}
if (currentMessage.sent || currentMessage.received) {
return (
<View style={[styles.headerItem, styles.tickView]}>
{currentMessage.sent && <Text style={[styles.standardFont, styles.tick, this.props.tickStyle]}>✓</Text>}
{currentMessage.received && <Text style={[styles.standardFont, styles.tick, this.props.tickStyle]}>✓</Text>}
</View>
);
}
return null;
}
renderUsername() {
const username = this.props.currentMessage.user.name;
if (username) {
const { containerStyle, wrapperStyle, ...usernameProps } = this.props;
if (this.props.renderUsername) {
return this.props.renderUsername(usernameProps);
}
return (
<Text style={[styles.standardFont, styles.headerItem, styles.username, this.props.usernameStyle]}>
{username}
</Text>
);
}
return null;
}
renderTime() {
if (this.props.currentMessage.createdAt) {
const { containerStyle, wrapperStyle, ...timeProps } = this.props;
if (this.props.renderTime) {
return this.props.renderTime(timeProps);
}
return (
<Time
{...timeProps}
containerStyle={{ left: [styles.timeContainer] }}
textStyle={{ left: [styles.standardFont, styles.headerItem, styles.time, timeProps.textStyle] }}
/>
);
}
return null;
}
renderCustomView() {
if (this.props.renderCustomView) {
return this.props.renderCustomView(this.props);
}
return null;
}
render() {
const isSameThread = isSameUser(this.props.currentMessage, this.props.previousMessage)
&& isSameDay(this.props.currentMessage, this.props.previousMessage);
const messageHeader = isSameThread ? null : (
<View style={styles.headerView}>
{this.renderUsername()}
{this.renderTime()}
{this.renderTicks()}
</View>
);
return (
<View style={[styles.container, this.props.containerStyle]}>
<TouchableOpacity
onLongPress={this.onLongPress}
accessibilityTraits="text"
{...this.props.touchableProps}
>
<View
style={[
styles.wrapper,
this.props.wrapperStyle,
]}
>
<View>
{this.renderCustomView()}
{messageHeader}
{this.renderMessageImage()}
{this.renderMessageText()}
</View>
</View>
</TouchableOpacity>
</View>
);
}
}
// Note: Everything is forced to be "left" positioned with this component.
// The "right" position is only used in the default Bubble.
const styles = StyleSheet.create({
standardFont: {
fontSize: 15,
},
slackMessageText: {
marginLeft: 0,
marginRight: 0,
},
container: {
flex: 1,
alignItems: 'flex-start',
},
wrapper: {
marginRight: 60,
minHeight: 20,
justifyContent: 'flex-end',
},
username: {
fontWeight: 'bold',
},
time: {
textAlign: 'left',
fontSize: 12,
},
timeContainer: {
marginLeft: 0,
marginRight: 0,
marginBottom: 0,
},
headerItem: {
marginRight: 10,
},
headerView: {
// Try to align it better with the avatar on Android.
marginTop: Platform.OS === 'android' ? -2 : 0,
flexDirection: 'row',
alignItems: 'baseline',
},
/* eslint-disable react-native/no-color-literals */
tick: {
backgroundColor: 'transparent',
color: 'white',
},
/* eslint-enable react-native/no-color-literals */
tickView: {
flexDirection: 'row',
},
slackImage: {
borderRadius: 3,
marginLeft: 0,
marginRight: 0,
},
});
Bubble.contextTypes = {
actionSheet: PropTypes.func,
};
Bubble.defaultProps = {
touchableProps: {},
onLongPress: null,
renderMessageImage: null,
renderMessageText: null,
renderCustomView: null,
renderTime: null,
currentMessage: {
text: null,
createdAt: null,
image: null,
},
nextMessage: {},
previousMessage: {},
containerStyle: {},
wrapperStyle: {},
tickStyle: {},
containerToNextStyle: {},
containerToPreviousStyle: {},
};
Bubble.propTypes = {
touchableProps: PropTypes.object,
onLongPress: PropTypes.func,
renderMessageImage: PropTypes.func,
renderMessageText: PropTypes.func,
renderCustomView: PropTypes.func,
renderUsername: PropTypes.func,
renderTime: PropTypes.func,
renderTicks: PropTypes.func,
currentMessage: PropTypes.object,
nextMessage: PropTypes.object,
previousMessage: PropTypes.object,
user: PropTypes.object,
containerStyle: PropTypes.shape({
left: ViewPropTypes.style,
right: ViewPropTypes.style,
}),
wrapperStyle: PropTypes.shape({
left: ViewPropTypes.style,
right: ViewPropTypes.style,
}),
messageTextStyle: Text.propTypes.style,
usernameStyle: Text.propTypes.style,
tickStyle: Text.propTypes.style,
containerToNextStyle: PropTypes.shape({
left: ViewPropTypes.style,
right: ViewPropTypes.style,
}),
containerToPreviousStyle: PropTypes.shape({
left: ViewPropTypes.style,
right: ViewPropTypes.style,
}),
};

this2.props is undefined with createTopTabBarNavigator

Inside tab bar navigator, i am using carousel library and onPress of item i want to navigate to different component. My first tab is having flatList on I am able to access this.props.navigation.navigate,
but in second tab where i am using carousel library inside _renderItem,
I am not able to access this.props.navigation.navigate. It always give error this2.props.....
(I am using react-navigation version 4.X)
export default class ListTab extends Component {
constructor(props) {
super(props);
console.info(this.props)
this.state = {
isLoading: true,
isConnected: false,
dataSource: []
}
}
componentDidMount = async () => {
await NetInfo.isConnected.addEventListener('connectionChange', this.handleConnectionChange)
AsyncStorage.getItem(USER_NAME, (error, result) => {
if(result) {
let data = {
method: 'POST',
credentials: 'same-origin',
mode: 'same-origin',
body: JSON.stringify({
'data': result,
}),
headers:{
'Accept': 'application/json',
'Content-Type': 'application/json',
}
}
if(this.state.isConnected) {
fetch(BaseUrl + 'my/endpoint/url', data)
.then((response) => response.json())
.then((responseJson)=> {
this.setState({
isLoading: false,
dataSource: responseJson.data
})
})
.catch((error) => {
console.log(error)
})
} else {
alert(NO_INTERNET)
}
} else {
console.log(error)
}
})
}
handleConnectionChange = async (isConnected) => {
await this.setState({isConnected});
}
_renderItem({item,index}) {
var allcat = [];
for(let i = 0; i < item.data.length; i++){
allcat.push(
<TouchableOpacity onPress={() => {this.props.navigation.naviate('FlavoursDetails')}}>
<Text style={styles.SectionListItemStyle}>{item.data[i].itemname}</Text>
</TouchableOpacity>
)
}
return (
<ScrollView style={{
flex:1, width:'100%',
shadowRadius: 4.65,elevation: 10, borderWidth:1, borderColor:'#ccc', margin:0, padding:0, borderRadius:10,marginTop:30, backgroundColor:'#fff', }}>
<Text style={styles.SectionHeaderStyle}>{item.title}</Text>
{allcat}
</ScrollView>
)
}
render() {
if(this.state.isLoading){
return(
<View style={{flex: 1, flexDirection:"column", alignItems:"center",alignSelf:"center", padding: 20}}>
<ActivityIndicator/>
</View>
)
}
return (
<ImageBackground style={{flex:1}}
source={require('../../assets/app_background.jpg')}>
<SafeAreaView style={{flex:1, alignItems:'center'}}>
<StatusBar
barStyle="light-content"
backgroundColor= {appColor}/>
<Carousel
ref={'carousel'}
data={this.state.dataSource}
sliderWidth={1000}
itemWidth={300}
renderItem={this._renderItem}/>
</SafeAreaView>
</ImageBackground>
);
}
}
const styles = StyleSheet.create({
SectionHeaderStyle: {
textAlign: 'left',
alignSelf: 'center',
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 3,
},
shadowOpacity: 0.29,
shadowRadius: 4.65,
elevation: 7,
fontWeight:"bold",
width:'100%',
backgroundColor : '#fff',
borderRadius:10,
color:'#001E41',
padding: 20,
fontSize: 18,
marginTop:0,
marginBottom:10,
},
SectionListItemStyle:{
fontSize : 15,
paddingLeft: 0,
paddingTop:10,
paddingBottom:10,
width:'85%',
color: appColor,
fontWeight:"normal",
backgroundColor : '#fff',
borderBottomWidth: 1,
alignSelf: "center",
borderColor: '#DDE0E5',
textAlign: 'left',
alignItems: 'center',
}
});
_renderItem({item,index}) {
var allcat = [];
for(let i = 0; i < item.data.length; i++){
allcat.push(
<TouchableOpacity onPress={() => {this.props.navigation.naviate('FlavoursDetails')}}>
<Text style={styles.SectionListItemStyle}>{item.data[i].itemname}</Text>
</TouchableOpacity>
)
}
Replace the above code with this:
_renderItem({item,index}) {
var allcat = [];
for(let i = 0; i < item.data.length; i++){
allcat.push(
<TouchableOpacity onPress={() => {this.props.navigation.navigate('FlavoursDetails')}}>
<Text style={styles.SectionListItemStyle}>{item.data[i].itemname}</Text>
</TouchableOpacity>
)
}

Proper way of using WebSockets with React Native

I'm new to React Native, but very familiar with React. As a beginner I'm looking to setup a connection between a cloud server and react-native with websockets as I've seen in the documentation. Unfortunately, there's no decent example out there that could help me out. This is all that I've got so far:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Button
} from 'react-native';
export default class raspberry extends Component {
constructor(props) {
super(props);
this.state = { open: false };
this.socket = new WebSocket('ws://127.0.0.1:3000');
this.emit = this.emit.bind(this);
}
emit() {
this.setState(prevState => ({ open: !prevState.open }))
this.socket.send("It worked!")
}
render() {
const LED = {
backgroundColor: this.state.open ? 'lightgreen' : 'red',
height: 30,
position: 'absolute',
flexDirection: 'row',
bottom: 0,
width: 100,
height: 100,
top: 120,
borderRadius: 40,
justifyContent: 'space-between'
}
return (
<View style={styles.container}>
<Button
onPress={this.emit}
title={this.state.open ? "Turn off" : "Turn on"}
color="#21ba45"
accessibilityLabel="Learn more about this purple button"
/>
<View style={LED}></View>
</View>
);
}
componentDidMount() {
this.socket.onopen = () => socket.send(JSON.stringify({ type: 'greet', payload: 'Hello Mr. Server!' }))
this.socket.onmessage = ({ data }) => console.log(JSON.parse(data).payload)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('raspberry', () => raspberry);
Everything works fine, but when I press the button to send a message, this is the error I get:
Cannot send a message. Unknown WebSocket id 1
I also made a test with a js client and everything worked smooth..looking to see how I could get this fixed or some example sources where I can figure it out.
change the code
socket.send(JSON.stringify({ type: 'greet', payload: 'Hello Mr. Server!' }))
to
this.socket.send(JSON.stringify({ type: 'greet', payload: 'Hello Mr. Server!' }))
it should work.
here is my code to test, based on your code and RN 0.45 (and project generated by create-react-native-app), connects to a public websocket server wss://echo.websocket.org/, on my android it works fine and I can see the websocket server's echo message after I push the button.
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Button
} from 'react-native';
export default class App extends React.Component {
constructor() {
super();
this.state = {
open: false
};
this.socket = new WebSocket('wss://echo.websocket.org/');
this.emit = this.emit.bind(this);
}
emit() {
this.setState(prevState => ({
open: !prevState.open
}))
this.socket.send("It worked!")
}
componentDidMount() {
this.socket.onopen = () => this.socket.send(JSON.stringify({type: 'greet', payload: 'Hello Mr. Server!'}));
this.socket.onmessage = ({data}) => console.log(data);
}
render() {
const LED = {
backgroundColor: this.state.open
? 'lightgreen'
: 'red',
height: 30,
position: 'absolute',
flexDirection: 'row',
bottom: 0,
width: 100,
height: 100,
top: 120,
borderRadius: 40,
justifyContent: 'space-between'
}
return (
<View style={styles.container}>
<Button onPress={this.emit} title={this.state.open
? "Turn off"
: "Turn on"} color="#21ba45" accessibilityLabel="Learn more about this purple button"/>
<View style={LED}></View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5
}
});
According to documentation you need to add state connected to your component. And send anything only if connected state is true.
export default class raspberry extends Component {
constructor(props) {
super(props);
this.state = {
open: false,
connected: false
};
this.socket = new WebSocket('ws://127.0.0.1:3000');
this.socket.onopen = () => {
this.setState({connected:true})
};
this.emit = this.emit.bind(this);
}
emit() {
if( this.state.connected ) {
this.socket.send("It worked!")
this.setState(prevState => ({ open: !prevState.open }))
}
}
}
After I've done some researches I found that the WebSocket should be
new WebSocket("ws://10.0.2.2:PORT/")
where 10.0.2.2 means the localhost

Navigator is not working properly in React Native

I followed one tutorial for react native development tutorial.They developed one IOS app using react native.In there they had used NavigatorIOS for navigation purpose.IOS app is working properly.But when I need to create android app I have to changed it to NavigatorIOS to Navigator.App loaded first view.but later on that is not working.
Here [https://www.raywenderlich.com/126063/react-native-tutorial][1] the link of tutorial which I have followed.How can I change code for Android.?
import React, { Component } from 'react';
import {
StyleSheet,
Text,
TextInput,
View,
TouchableHighlight,
ActivityIndicator,
Image
} from 'react-native';
var SearchResults = require('./SearchResults');
function urlForQueryAndPage(key, value, pageNumber) {
var data = {
country: 'uk',
pretty: '1',
encoding: 'json',
listing_type: 'buy',
action: 'search_listings',
page: pageNumber
};
data[key] = value;
var querystring = Object.keys(data)
.map(key => key + '=' + encodeURIComponent(data[key]))
.join('&');
return 'http://api.nestoria.co.uk/api?' + querystring;
};
class SearchPage extends Component {
constructor(props) {
super(props);
this.state = {
searchString: 'london',
isLoading: false,
message: ''
};
}
onSearchTextChanged(event) {
console.log('onSearchTextChanged');
this.setState({ searchString: event.nativeEvent.text });
console.log(this.state.searchString);
}
_executeQuery(query) {
console.log(query);
this.setState({ isLoading: true });
fetch(query)
.then(response => response.json())
.then(json => this._handleResponse(json.response))
.catch(error =>
this.setState({
isLoading: false,
message: 'Something bad happened ' + error
}));
}
onLocationPressed() {
navigator.geolocation.getCurrentPosition(
location => {
var search = location.coords.latitude + ',' + location.coords.longitude;
this.setState({ searchString: search });
var query = urlForQueryAndPage('centre_point', search, 1);
this._executeQuery(query);
},
error => {
this.setState({
message: 'There was a problem with obtaining your location: ' + error
});
});
}
_handleResponse(response) {
this.setState({ isLoading: false , message: '' });
if (response.application_response_code.substr(0, 1) === '1') {
this.props.navigator.push({
title: 'Results',
component: SearchResults,
passProps: {listings: response.listings}
});
} else {
this.setState({ message: 'Location not recognized; please try again.'});
}
}
onSearchPressed() {
var query = urlForQueryAndPage('place_name', this.state.searchString, 1);
this._executeQuery(query);
}
render() {
var spinner = this.state.isLoading ?
( <ActivityIndicator
size='large'/> ) :
( <View/>);
console.log('SearchPage.render');
return (
<View style={styles.container}>
<Text style={styles.description}>
Search for houses to buy!
</Text>
<Text style={styles.description}>
Search by place-name, postcode or search near your location.
</Text>
<View style={styles.flowRight}>
<TextInput
style={styles.searchInput}
value={this.state.searchString}
onChange={this.onSearchTextChanged.bind(this)}
placeholder='Search via name or postcode'/>
<TouchableHighlight style={styles.button}
underlayColor='#99d9f4'
onPress={this.onSearchPressed.bind(this)}>
<Text style={styles.buttonText}>Go</Text>
</TouchableHighlight>
</View>
<View style={styles.flowRight}>
<TouchableHighlight style={styles.button}
underlayColor='#99d9f4'
onPress={this.onLocationPressed.bind(this)}>
<Text style={styles.buttonText}>Location</Text>
</TouchableHighlight>
</View>
<Image source={require('./Resources/house.png')} style={styles.image}/>
{spinner}
<Text style={styles.description}>{this.state.message}</Text>
</View>
);
}
}
var styles = StyleSheet.create({
description: {
marginBottom: 20,
fontSize: 18,
textAlign: 'center',
color: '#656565'
},
container: {
padding: 30,
marginTop: 80,
alignItems: 'center'
},
flowRight: {
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'stretch'
},
buttonText: {
fontSize: 18,
color: 'white',
alignSelf: 'center'
},
button: {
height: 36,
flex: 1,
flexDirection: 'row',
backgroundColor: '#48BBEC',
borderColor: '#48BBEC',
borderWidth: 1,
borderRadius: 8,
marginBottom: 10,
alignSelf: 'stretch',
justifyContent: 'center'
},
searchInput: {
height: 36,
padding: 4,
marginRight: 5,
flex: 4,
fontSize: 18,
borderWidth: 1,
borderColor: '#48BBEC',
borderRadius: 8,
color: '#48BBEC'
},image: {
width: 217,
height: 138
}
});
module.exports = SearchPage;

Resources