I have this code and I wanna login using the link in the fetch of this below code but I'm getting this error while clicking on the login button: JSON Parse Error: Unexpected EOF. I'm trying to use rest API for this login app.
var React = require('react');
var ReactNative = require('react-native');
var t = require('tcomb-form-native');
var {
AppRegistry,
AsyncStorage,
StyleSheet,
Text,
View,
TouchableHighlight,
AlertIOS,
Image,
} = ReactNative;
var STORAGE_KEY = 'id_token';
var Form = t.form.Form;
var Person = t.struct({
username: t.String,
password: t.String
});
const options = {};
var AwesomeProject = React.createClass({
async _onValueChange(item, selectedValue) {
try {
await AsyncStorage.setItem(item, selectedValue);
} catch (error) {
console.log('AsyncStorage error: ' + error.message);
}
},
componentDidMount: function() {
this._userLogin();
},
_userLogin: function() {
var value = this.refs.form.getValue();
if (value) { // if validation fails, value will be null
fetch("http://vowelserver.com/trades/test_autheticate/", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: value.username,
password: value.password,
})
}).then((response) => response.json())
.then((responseData) => {
this._onValueChange(STORAGE_KEY, responseData.id_token)
}).done();
}
},
render() {
return (
<View style={styles.container}>
<View style={styles.container}>
<Image
resizeMode="contain"
source={{uri: 'http://res.cloudinary.com/vowelweb/image/upload/v1498114115/Logo_mqzlgt.png'}}
style={styles.image}
/>
</View>
<View style={styles.row}>
<Form
ref="form"
type={Person}
options={options}
/>
</View>
<View style={styles.row}>
<TouchableHighlight style={styles.button} onPress={this._userLogin} underlayColor='#99d9f4'>
<Text style={styles.buttonText}>Login</Text>
</TouchableHighlight>
</View>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
justifyContent: 'center',
marginTop: 50,
padding: 20,
backgroundColor: '#ffffff',
},
containers: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
backgroundColor: 'white',
position: 'relative',
borderBottomWidth: 1,
},
title: {
fontSize: 30,
alignSelf: 'center',
marginBottom: 30
},
buttonText: {
fontSize: 18,
color: 'white',
alignSelf: 'center'
},
button: {
height: 36,
backgroundColor: '#48BBEC',
borderColor: '#48BBEC',
borderWidth: 1,
borderRadius: 8,
marginBottom: 10,
alignSelf: 'stretch',
justifyContent: 'center'
},
login: {
flex: 1,
backgroundColor: '#efeff2',
alignItems: 'center',
justifyContent: 'center',
},
image: {
position: 'absolute',
top: 0,
bottom: 0,
left: 30,`enter code here`
right: 30,
},
});
AppRegistry.registerComponent('FirstRun', () => AwesomeProject);
This line...
(response) => response.json()
assumes that you are getting a string that is parseable into JSON.
Try inspecting the response.
Pleas find the code snippet for the simple fetch api call in react.make sure you have valid url which will return you the response
getMoviesFromApiAsync = () => {
return fetch('http://droidtute.com/reactexample/sample_api/getMovieList.php')
.then((response) => response.json())
.then((responseJson) => {
// alert(JSON.stringify(responseJson))
this.setState({ moviesList: responseJson.movieList }) // this will update state to re-render ui
return responseJson.movieList;
})
.catch((error) => {
console.error(error);
});
}
Related
I get this error :
"TypeError: undefined is not an object (evaluating '_firebase.database.ref')"
I don't understand why this error is happening.
This is the code:
import { useNavigation } from '#react-navigation/core'
import React, { useState } from 'react'
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'
import { auth, database } from '../firebase'
const HomeScreen = () => {
const navigation = useNavigation()
const [led1Status, setLed1Status] = useState("1")
const handleSignOut = () => {
auth
.signOut()
.then(() => {
navigation.replace("Login")
})
.catch(error => alert(error.message))
}
const handleLed1Toggle = () => {
const firebaseRef = database.ref().child("Led1Status")
if (led1Status === "1") {
firebaseRef.set("0")
setLed1Status("0")
} else {
firebaseRef.set("1")
setLed1Status("1")
}
}
return (
<><View style={styles.container}>
<Text>Email: {auth.currentUser?.email}</Text>
<TouchableOpacity
onPress={handleSignOut}
style={styles.button}
>
<Text style={styles.buttonText}>Sign out</Text>
</TouchableOpacity>
</View>
<View style={styles.bruhst}>
<TouchableOpacity
onPress={handleLed1Toggle}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>Say it</Text>
</TouchableOpacity>
</View></>
)
}
export default HomeScreen
const styles = StyleSheet.create({
bruhst: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
container: {
flex: 1,
marginTop: 30,
marginLeft: 20,
},
button: {
backgroundColor: '#F2ACB9',
width: '50%',
padding: 15,
borderRadius: 10,
alignItems: 'center',
marginTop: 15,
},
buttonText: {
color: 'white',
fontWeight: '700',
fontSize: 16,
},
buttonOutline: {
backgroundColor: 'white',
},
buttonOutlineText: {
color: '#F2ACB9',
fontWeight:'700',
fontSize: 16,
},
})
I am working on a mobile app with a button. im trying to make the button 'Say it' when pressed to change the value of the key from the realtime database from firebase from a 0 to a 1. the key name on the realtie database is Led1Status.
I couldn't find a way to upload image to the firestore database with url while I am submitting the I am getting the file path like file:///data/user/0/com.kk/cache/rn_image_picker_lib_temp_6e973dbe-ab8f, but I need to get file path with url in firestore. Could anyone help with this?. Below is my code to upload image with form.
import React, { useState } from "react";
import { View,StyleSheet,Text, ScrollView, Pressable, Image, TextInput } from 'react-native';
import { Button } from "react-native-elements";
import {firebase} from '#react-native-firebase/firestore';
import { launchImageLibrary } from "react-native-image-picker";
export default function Test(){
const [username,setusername] = useState('');
const [email,setemail] = useState('');
const[imageURI,setImageURI] = useState(null);
const handleOpenLibrary = async () => {
let options = {
mediaType: "photo",
};
const imageData = await launchImageLibrary(options);
setImageURI(imageData.assets[0].uri);
};
function create(){
firebase.firestore()
.collection('Actors')
.add({
name: username,
email: email,
image: {uri:imageURI},
}).then(() => {
console.log("data submitted");
}).catch((error)=> {
console.log(error);
});;
} return (
<View style={styles.body}>
<View style={styles.row}>
<TextInput
style={{backgroundColor:'white'}}
value={username}
onChangeText= {(username) => {setusername(username)}}
placeholder="Enter name"/>
</View>
<View style={styles.row}>
<TextInput
style={{backgroundColor:'white'}}
value={email}
onChangeText= {(email) => {setemail(email)}}
placeholder="Enter email"/>
</View>
<View style={styles.imageContainer}>
<Image
source={{uri:imageURI}}
style={styles.imageBox}
resizeMode='contain'
/>
</View>
<Button
title="submit"
onPress={create}/>
<Button title="pick" onPress={handleOpenLibrary}/>
</View>
)}
const styles = StyleSheet.create({
body: {
flex: 1,
flexDirection: 'column',
backgroundColor: 'black',
alignItems: 'center',
justifyContent: 'flex-start',
},
text: {
fontSize: 40,
margin: 10,
},
row: {
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent:'space-between',
},
footer: {
position: 'absolute',
flex:0.1,
left: 0,
right: 0,
bottom: -10,
flexDirection:'row',
height:50,
alignItems:'center',
justifyContent:'center',
borderRadius:10,
},
footerText: {
color:'white',
fontWeight:'bold',
alignItems:'center',
fontSize:18,
},
imageContainer: {
marginVertical: 20,
borderWidth: 5,
borderColor: '#ff5555'
},
imageBox: {
width: 256,
height: 256
}
});
I am trying to use the GooglePlacesAutocomplete, but once I make the address query, for example: "São C" and the "listView" return something like: "São Caetano, São Paulo ...", but when I try to select one option it seems like the list is not visible, because and the selection do not affect the item list.
this is the code I am using:
import * as React from 'react';
import { Platform, StyleSheet, Text, View } from 'react-native';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
import { colors, device, fonts } from '../constants';
// icons
import SvgTruck from './icons/Svg.Truck';
//const { onLocationSelected } = this.props
// constants
const GOOGLE_MAPS_APIKEY = '[API KEY]'
const WhereTo = () => (
<View style={styles.container}>
<View style={styles.containerBanner}>
<Text style={styles.bannerText}>15% off, up to $6.00</Text>
<Text style={styles.bannerMuted}>3 days</Text>
</View>
<View style={styles.containerInput} >
<View style={styles.containerSquare}>
<View style={styles.square} />
</View>
<GooglePlacesAutocomplete
styles={{
textInputContainer: {
flex: 1,
backgroundColor: 'transparent',
height: 54,
marginHorizontal: 20,
borderTopWidth: 0,
borderBottomWidth:0
},
textInput: {
height: 45,
left:0,
margin: 0,
borderRadius: 0,
paddingTop: 0,
paddingBottom: 0,
paddingLeft: 0,
paddingRight: 0,
padding: 0,
marginTop: 0,
marginLeft: 0,
marginRight: 0,
fontSize:18
},
listView: {
position:'absolute',
marginTop: 50
},
description: {
fontSize:16
},
row: {
padding: 18,
height:58
}
}}
placeholder="Para onde?"
onPress={(data, details) => {
// 'details' is provided when fetchDetails = true
console.log(data, details);
}}
query={{
key: GOOGLE_MAPS_APIKEY,
language: 'pt',
components: "country:br"
}}
textInputProps={{
autoCapitalize: "none",
autoCorrect: false
}}
fetchDetails
enablePoweredByContainer={false}
/>
<View style={styles.containerIcon}>
<SvgTruck />
</View>
</View>
</View>
);
const styles = StyleSheet.create({
container: {
top: Platform.select({ ios: 60, android: 40 }),
alignSelf: 'center',
position: 'absolute',
shadowColor: colors.black,
shadowOffset: { height: 2, width: 0 },
shadowOpacity: 0.2,
shadowRadius: 8,
top: device.iPhoneX ? 144 : 120,
width: device.width - 40
},
containerBanner: {
backgroundColor: colors.green,
borderTopLeftRadius: 4,
borderTopRightRadius: 4,
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 8
},
bannerText: {
color: colors.white,
fontFamily: fonts.uberMedium,
fontSize: 12
},
bannerMuted: {
color: colors.mint,
fontFamily: fonts.uberMedium,
fontSize: 12
},
containerInput: {
alignItems: 'center',
backgroundColor: colors.white,
flexDirection: 'row',
height: 48
},
containerSquare: {
alignItems: 'center',
flex: 0.15
},
square: {
backgroundColor: colors.black,
height: 8,
width: 8
},
containerIcon: {
alignItems: 'center',
borderLeftColor: colors.greyMercury,
borderLeftWidth: 1,
flex: 0.2
}
});
export default WhereTo;
Can anyone trying to help me to solve it?
I recreated the Expo project and now it works, I could not found the root cause, but once that other project was made by other person and Expo make it easy to do and configure, it was fast enoght to create.
export default function AskForDriver () {
const [location, setLocation] = useState("");
const [errorMsg, setErrorMsg] = useState("");
useEffect(() => {
(async () => {
let { status } = await Location.requestPermissionsAsync();
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied');
}
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
})();
}, []);
let text = 'Waiting..';
if (errorMsg) {
text = errorMsg;
} else if (location) {
text = JSON.stringify(location);
console.log('location - latitude: ', location.coords.latitude)
console.log('location - longitude: ', location.coords.longitude)
}
return (
<View style={styles.container}>
<View style={styles.mainHeader}>
<Text style={styles.fontHeader}>Incluir flatlist com promoções e mensagens de incentivos</Text>
</View>
<View style={styles.searchHeader}>
<GooglePlacesAutocomplete
currentLocation
//styles={styles.placesautocomplete}
styles={{
textInputContainer: {
backgroundColor: 'grey',
},
placesautocomplete: {
flex:1,
},
textInput: {
height: 38,
color: '#5d5d5d',
fontSize: 16,
},
predefinedPlacesDescription: {
color: '#1faadb',
},
}}
placeholder='Search'
onPress={(data, details = null) => {
// 'details' is provided when fetchDetails = true
console.log(data, details);
}}
query={{
key: 'YOUR API KEY',
language: 'pt',
components: 'country:br',
}}
/>
</View>
<MapView
style={styles.mapStyle}
showsMyLocationButton
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
>
</MapView>
{//<Text>{text}</Text>
}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
position: 'absolute',
alignContent:'center',
margin:0
},
mainHeader: {
backgroundColor: '#10002b',
padding:10,
},
fontHeader: {
color: '#e0aaff',
fontSize: 15,
},
searchHeader: {
borderColor: '#333',
borderWidth:5,
},
mapStyle: {
flex:1,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
});
Trying out react navigation v5 so I created a login register form that brings the user to the dashboard if he's logged in before using AsyncStorage. It works fine but I would like to know how to improve on the structure of code. Currently, I put all the components in a stack navigator, but things might get messy if I were to add more screens. Also, I would be switching to hooks but am confused if and how I should apply useContext useMemo useEffect
App.js file
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import Login from './components/login';
import Signup from './components/signup';
import Dashboard from './components/dashboard';
import AuthLoading from './components/authLoading'
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator
initialRouteName="AuthLoading"
screenOptions={{
headerTitleAlign: 'center',
headerStyle: {
backgroundColor: '#3740FE',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}>
<Stack.Screen
name="AuthLoading"
component={AuthLoading}
options={
{title: 'AuthLoading'},
{headerLeft:null}
}/>
<Stack.Screen
name="Signup"
component={Signup}
options={{ title: 'Signup' }}
/>
<Stack.Screen
name="Login"
component={Login}
options={
{ title: 'Login' },
{ headerLeft: null }
}
/>
<Stack.Screen
name="Dashboard"
component={Dashboard}
options={
{ title: 'Dashboard' },
{ headerLeft: null }
}
/>
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}
authLoading.js file
import React from 'react';
import { ActivityIndicator, StatusBar, StyleSheet, View, Text } from 'react-native';
import {AsyncStorage} from 'react-native'
export default class AuthLoadingScreen extends React.Component {
constructor(props) {
super(props);
this.checkUserToken();
}
async checkUserToken() {
const isLoggedIn = await AsyncStorage.getItem('isLoggedIn');
console.log(isLoggedIn)
// If User Token
if (isLoggedIn === '1') {
//AsyncStorage.setItem(isLoggedIn);
this.props.navigation.navigate('Dashboard');
}
else {
this.props.navigation.navigate('Login');
}
}
// Render any loading content that you like here
render() {
return (
<View style={styles.container}>
<Text style={styles.text}>Checking Authentication</Text>
<ActivityIndicator />
<StatusBar barStyle="default" />
</View>
);
}
}
// Styles
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#CA3433',
justifyContent: 'center',
alignItems: 'center',
},
text: {
justifyContent: 'center',
color: '#fff',
fontSize: 18,
fontWeight: '500',
},
});
signup.js file
import React, { Component } from 'react';
import { StyleSheet, Text, View, TextInput, Button, Alert, ActivityIndicator } from 'react-native';
import firebase from '../database/firebase';
export default class Signup extends Component {
constructor() {
super();
this.state = {
displayName: '',
email: '',
password: '',
isLoading: false
}
}
updateInputVal = (val, prop) => {
const state = this.state;
state[prop] = val;
this.setState(state);
}
registerUser = () => {
if (this.state.email === '' && this.state.password === '') {
Alert.alert('Enter details to signup!')
} else {
this.setState({
isLoading: true,
})
firebase
.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password)
.then((res) => {
res.user.updateProfile({
displayName: this.state.displayName
})
console.log('User registered successfully!')
this.setState({
isLoading: false,
displayName: '',
email: '',
password: ''
})
this.props.navigation.navigate('Login')
})
.catch(error => this.setState({
isLoading: false,
errorMessage: error.message
}))
}
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E" />
</View>
)
}
return (
<View style={styles.container}>
<TextInput
style={styles.inputStyle}
placeholder="Name"
value={this.state.displayName}
onChangeText={(val) => this.updateInputVal(val, 'displayName')}
/>
<TextInput
style={styles.inputStyle}
placeholder="Email"
value={this.state.email}
onChangeText={(val) => this.updateInputVal(val, 'email')}
/>
<TextInput
style={styles.inputStyle}
placeholder="Password"
value={this.state.password}
onChangeText={(val) => this.updateInputVal(val, 'password')}
maxLength={15}
secureTextEntry={true}
/>
<Button
color="#3740FE"
title="Signup"
onPress={() => this.registerUser()}
/>
<Text>{this.state.errorMessage}</Text>
<Text
style={styles.loginText}
onPress={() => this.props.navigation.navigate('Login')}>
Already Registered? Click here to login
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
display: "flex",
flexDirection: "column",
justifyContent: "center",
padding: 35,
backgroundColor: '#fff'
},
inputStyle: {
width: '100%',
marginBottom: 15,
paddingBottom: 15,
alignSelf: "center",
borderColor: "#ccc",
borderBottomWidth: 1
},
loginText: {
color: '#3740FE',
marginTop: 25,
textAlign: 'center'
},
preloader: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'absolute',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff'
}
});
login.js file
import React, { Component } from 'react';
import { StyleSheet, Text, View, TextInput, Button, Alert, ActivityIndicator } from 'react-native';
import firebase from '../database/firebase';
import {AsyncStorage} from 'react-native';
export default class Login extends Component {
constructor() {
super();
this.state = {
email: '',
password: '',
isLoading: false,
errorMessage: ''
}
}
updateInputVal = (val, prop) => {
const state = this.state;
state[prop] = val;
this.setState(state);
}
/**
*
*/
userLogin = () => {
if (this.state.email === '' && this.state.password === '') {
this.setState({
errorMessage: "Enter details to sign in"
})
//Alert.alert('Enter details to signin!')
} else {
this.setState({
isLoading: true,
})
firebase
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then((res) => {
console.log(res)
console.log('User logged-in successfully!')
this.setState({
isLoading: false,
email: '',
password: ''
})
AsyncStorage.setItem('isLoggedIn', '1')
this.props.navigation.navigate('Dashboard')
})
.catch(error => this.setState({
errorMessage: 'Wrong email/password',
isLoading: false
}))
}
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E" />
</View>
)
}
return (
<View style={styles.container}>
<TextInput
style={styles.inputStyle}
placeholder="Email"
value={this.state.email}
onChangeText={(val) => this.updateInputVal(val, 'email')}
/>
<TextInput
style={styles.inputStyle}
placeholder="Password"
value={this.state.password}
onChangeText={(val) => this.updateInputVal(val, 'password')}
maxLength={15}
secureTextEntry={true}
/>
<Button
color="#3740FE"
title="Signin"
onPress={() => this.userLogin()}
/>
{/* style this */}
<Text>{this.state.errorMessage}</Text>
<Text
style={styles.loginText}
onPress={() => this.props.navigation.navigate('Signup')}>
Don't have account? Click here to signup
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
display: "flex",
flexDirection: "column",
justifyContent: "center",
padding: 35,
backgroundColor: '#fff'
},
inputStyle: {
width: '100%',
marginBottom: 15,
paddingBottom: 15,
alignSelf: "center",
borderColor: "#ccc",
borderBottomWidth: 1
},
loginText: {
color: '#3740FE',
marginTop: 25,
textAlign: 'center'
},
preloader: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'absolute',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff'
}
});
dashboard.js file
import React, { Component } from 'react';
import { StyleSheet, Text, View, TextInput, Button, Alert, ActivityIndicator } from 'react-native';
import firebase from '../database/firebase';
import {AsyncStorage} from 'react-native';
export default class Login extends Component {
constructor() {
super();
this.state = {
email: '',
password: '',
isLoading: false,
errorMessage: ''
}
}
updateInputVal = (val, prop) => {
const state = this.state;
state[prop] = val;
this.setState(state);
}
/**
*
*/
userLogin = () => {
if (this.state.email === '' && this.state.password === '') {
this.setState({
errorMessage: "Enter details to sign in"
})
//Alert.alert('Enter details to signin!')
} else {
this.setState({
isLoading: true,
})
firebase
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then((res) => {
console.log(res)
console.log('User logged-in successfully!')
this.setState({
isLoading: false,
email: '',
password: ''
})
AsyncStorage.setItem('isLoggedIn', '1')
this.props.navigation.navigate('Dashboard')
})
.catch(error => this.setState({
errorMessage: 'Wrong email/password',
isLoading: false
}))
}
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E" />
</View>
)
}
return (
<View style={styles.container}>
<TextInput
style={styles.inputStyle}
placeholder="Email"
value={this.state.email}
onChangeText={(val) => this.updateInputVal(val, 'email')}
/>
<TextInput
style={styles.inputStyle}
placeholder="Password"
value={this.state.password}
onChangeText={(val) => this.updateInputVal(val, 'password')}
maxLength={15}
secureTextEntry={true}
/>
<Button
color="#3740FE"
title="Signin"
onPress={() => this.userLogin()}
/>
{/* style this */}
<Text>{this.state.errorMessage}</Text>
<Text
style={styles.loginText}
onPress={() => this.props.navigation.navigate('Signup')}>
Don't have account? Click here to signup
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
display: "flex",
flexDirection: "column",
justifyContent: "center",
padding: 35,
backgroundColor: '#fff'
},
inputStyle: {
width: '100%',
marginBottom: 15,
paddingBottom: 15,
alignSelf: "center",
borderColor: "#ccc",
borderBottomWidth: 1
},
loginText: {
color: '#3740FE',
marginTop: 25,
textAlign: 'center'
},
preloader: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'absolute',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff'
}
});
React-Navigation provided help regarding the auth flow on their official site. Just follow the below link
https://reactnavigation.org/docs/auth-flow/
Note: You can follow this article for authentication flow using hooks and react-navigation 5
https://dev.to/embeddednature/create-an-authorization-flow-with-react-navigation-5-x-2pkh
I have a small problem with updating an Image source (that was dynamically created in a map) after making a different Firebase query to compare statuses of users to each other.
import React from 'react';
import { ActivityIndicator, Dimensions, Image, Button, StyleSheet, Text, TouchableOpacity, ScrollView, View } from 'react-native';
import IconTabs from './IconTabs.js';
import firebase from 'firebase';
export default class Forest extends React.Component {
static navigationOptions = {
header: <IconTabs />,
}
constructor() {
super();
this.state = {
users: [],
showLoading: true,
};
this.onPress = this.onPress.bind(this);
}
componentDidMount() {
let whichGender = null;
if (global_user_gender === 'male') {
whichGender = 'female';
} else if (global_user_gender === 'female') {
whichGender = 'male';
} else {
console.warn("Error! This user has no gender somehow!");
}
let arrayOfPromises = new Promise((resolve, reject) => {
firebase.database().ref()
.child('users').orderByChild('gender').equalTo(whichGender).on('value', data => {
resolve(Object.values(data.val()))
this.setState({showLoading: false});
this.setState({users: Object.values(data.val())});
this.state.users.map(user => {
// console.log("user id: ", user.id);
firebase.database().ref(`/bonds/${global_user_id}_${user.id}`)
.on('value', data => {
if(data.exists()) {
// this.state.users.setState({bondStatus: data.val().bond})
console.log(`${user.id} like or match found. Are they matched?`, data.val().bond);
}
})
});
})
})
}
onPress(data) {
global.others_data = data;
this.props.navigation.navigate('OthersScreen');
}
render() {
return (
<ScrollView>
{
this.state.showLoading &&
<View>
<Image style={styles.bird} source={require('../assets/colibri-logo.png')} />
<Text style={styles.loadtext}>Loading</Text>
<ActivityIndicator size="large" />
</View>
}
<View style={styles.container}>
{
this.state.users.map(user => {
return (
<View key={user.id} keyProp={user.id} ref={user.id}>
<TouchableOpacity onPress={() => this.onPress(user)}>
<Image
source={{uri:`data:image/gif;base64,${user.pic}`}}
style={styles.circleimage}
/>
</TouchableOpacity>
<Text>{user.bio}</Text>
</View>
)
})
}
</View>
</ScrollView>
)
}
}
let deviceWidth = Dimensions.get('window').width;
const styles = StyleSheet.create({
container: {
flex: 1,
width: deviceWidth,
flexDirection: 'row',
justifyContent: 'space-evenly',
flexWrap: 'wrap',
alignSelf: 'center',
},
text: {
textAlign: 'center',
fontSize: 30,
marginTop: 20,
marginBottom: 10,
},
text2: {
textAlign: 'center',
fontSize: 20,
fontStyle: 'italic',
marginLeft: 20,
marginRight: 20,
height: 100,
},
loadtext: {
alignSelf: 'center',
marginBottom: 10,
},
button: {
width: deviceWidth - 40,
paddingTop: 10,
marginBottom: 20,
alignSelf: 'center',
},
circleimage: {
height: 150,
width: 150,
borderRadius: 125,
alignSelf: 'center',
marginTop: 10,
marginBottom: 20,
},
circleimagered: {
height: 200,
width: 200,
backgroundColor: 'red',
borderRadius: 125,
alignSelf: 'center',
marginTop: 10,
marginBottom: 20,
},
bird: {
width: 200,
height: 200,
marginTop: 20,
marginBottom: 50,
alignSelf: 'center',
},
});
The console.log("${user.id} like or match found. Are they matched?", data.val().bond); returns this:
EXbmej7RpVY0VvKvVgHSEfJV6Zm2 like or match found. Are they matched?
true Goo6wObYoHZmUBsgoFs8nLoCMMs1 like or match found. Are they
matched? true MMo7kRByoYM7lowyTTNf1XJkmka2 like or match found. Are
they matched? false
What I want to do to those 3 users is draw a color circle around their icon, but everything I tried failed up until now. I found something that sort of does what I want, but when I tested it it also didn't work: https://codepen.io/PiotrBerebecki/pen/PGaxdx
Can you please help me get my user's icons to look like in this
picture?
In the end I got it to work by extending the query with a query inside it. Strangely, mapping normally requires a return, but in this case it didn't...? Whatever, works as I want now:
componentDidMount() {
let whichGender = null;
if (global_user_gender === "male") {
whichGender = "female";
} else if (global_user_gender === "female") {
whichGender = "male";
} else {
console.warn("Error! This user has no gender somehow!");
}
firebase.database().ref()
.child("users").orderByChild("gender").equalTo(whichGender)
.on("value", data => {
let updatedUsers = [];
Object.values(data.val()).map(user => {
firebase.database().ref(`/bonds/${global_user_id}_${user.id}`)
.on("value", bond => {
if (bond.exists()) {
if(bond.val().bond) {
user.borderColor = 'red';
} else {
user.borderColor = 'green';
}
user.borderWidth = 7;
updatedUsers.push({
age: user.age,
bio: user.bio,
borderColor: user.borderColor,
borderWidth: user.borderWidth,
firstName: user.firstName,
gender: user.gender,
id: user.id,
lastName: user.lastName,
pic: user.pic
})
this.setState({ users: updatedUsers });
} else {
firebase.database().ref(`/bonds/${user.id}_${global_user_id}`)
.on("value", bond2 => {
if (bond2.exists()) {
if(bond2.val().bond) {
user.borderColor = 'red';
} else {
user.borderColor = 'blue';
}
user.borderWidth = 7;
updatedUsers.push({
age: user.age,
bio: user.bio,
borderColor: user.borderColor,
borderWidth: user.borderWidth,
firstName: user.firstName,
gender: user.gender,
id: user.id,
lastName: user.lastName,
pic: user.pic
})
this.setState({ users: updatedUsers });
} else {
user.borderColor = 'white';
user.borderWidth = 0;
updatedUsers.push({
age: user.age,
bio: user.bio,
borderColor: user.borderColor,
borderWidth: user.borderWidth,
firstName: user.firstName,
gender: user.gender,
id: user.id,
lastName: user.lastName,
pic: user.pic
})
this.setState({ users: updatedUsers });
}
})
}
})
this.setState({ showLoading: false });
})
})
}
Working example