How to find if users exist in Firebase? - reactjs

I am using Firebase Web SDK and know methods to check whether a child in a collection exists or not. However I can't find a concise example checking the existence of a user, without trying to sign him/her in.
export class Email extends Component {
constructor (props) {
super(props)
this.state = { email: '' }
}
checkEmail () {
const { email } = this.state
FirebaseApp.auth()
.createUserWithEmailAndPassword(email, uuid.v4())
.then((User) => Actions.Password({ User }))
.catch((error) => {
// Handle Errors here.
console.log('firebase', {error})
this.setState({error})
// ...
})
// Actions.password()
}
render () {
return (
<View style={{ ...styles.onboarding, backgroundColor: 'purple' }}>
<View style={{ borderBottomWidth: 3, borderColor: 'black', padding: 10 }}>
<TextInput ref='email'
style={styles.input}
keyboardType='email-address'
placeholder='Your email'
value={this.state.email}
onChangeText={(email) => this.setState({email: email.toLowerCase()})} />
</View>
{!this.state.error ? null
: <Text>
{this.state.error.message}
</Text>
}
<TouchableOpacity onPress={() => this.checkEmail()} style={{ ...styles.button, margin: 20, borderColor: 'black' }}>
<Text style={styles.buttonText}>Next</Text>
</TouchableOpacity>
</View>
)
}
}
Do you have any piece of code we could reuse?

For the moment, and because it complies with my app security policy and setup, I created an email collection indexed precisely by ids.
firebase.ref(`emails/${user.email}`).set(true)

Related

API call doesn't render on the screen despite displaying json in the command line (React native)

I'm a bit new to react native and I've been self learning for a couple of months now but I've hit a road block that I Just can't seem to surmount.
I'm trying to get my app to display a flatlist of data that is called from my API. The JSON shows on the command line but nothing displays on the client. I'm not sure if the problem is that I'm calling it wrong or something else
state = {
clubs: [
]
}
componentDidMount() {
let url = 'https://api.statorium.com/api/v1/standings/143?apikey=***************'
fetch(url)
.then((response) => response.text())
.then((json) => {
console.log('JSON', json)
this.setState({ clubs: json })
return json;
})
.catch((error) => {
console.error(error);
this.setState({ clubs: [] })
})
}
onChangeText(text) {
console.log('textChanged', text)
}
ItemView(item) {
return (
<View>
<Text>{item.teamName}</Text>
</View>
);
};
render() {
return (
<View style={styles.container1}>
<SafeAreaView >
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: 'white', borderRadius: 10, }}>
<View>
<Ionicons name='md-search' size={25} color='black' style={{ marginLeft: 10 }} />
</View>
<TextInput
style={styles.input}
placeholder="Search Player"
onChangeText={text => this.onChangeText(text)}
/>
</View>
</SafeAreaView>
<FlatList
data={this.state.clubs.standings}
renderItem={item => this.ItemView(item)}
ListEmptyComponent={() => (
<Text style={{ color: 'white' }}>
Nothing to show
</Text>
)
}
/>
</View>
)
}
}
The API (I'm just trying to get the team name's displayed for now)
```JSON {"gmtUpdated":1662137635,"season":
{"seasonID":143,"leagueID":"24","seasonName":"2022","fullName":"Major League Soccer
(United States) 2022","stages":false,"groups":[{"groupID":"192","groupName":"Eastern
Conference","standings":[{"teamID":"467","teamName":"Philadelphia Union","options":"
{\"played_chk\":\"29\",\"winhome_chk\":\"10\",\"winaway_chk\":\"6\",\"drawhome_chk\":\"
5\",\"drawaway_chk\":\"4\",\"losthome_chk\":\"0\",\"lostaway_chk\":\"4\",\"home_win_pts
\":\"10\",\"away_win_pts\":\"6\",\"home_draw_pts\":\"5\",\"away_draw_pts\":\"4\",\"home
_loose_pts\":\"0\",\"away_loose_pts\":\"4\",\"home_bonus\":\"0.00\",\"away_bonus\":\"0.
00\",\"goalscore_chk\":\"61\",\"goalconc_chk\":\"21\",\"home_points\":\"0.00\",\"away_p
oints\":\"0.00\",\"id\":\"467\",\"win_chk\":16,\"draw_chk\":9,\"lost_chk\":4,\"diff_chk
\":\"61 - 21\",\"gd_chk\":40,\"point_chk\":57,\"bonuspts_chk\":0,\"percent_chk\":\"0.707\",\"poin
tshome_chk\":35,\"pointsaway_chk\":22,\"otwin_chk\":0,\"otlost_chk\":0,\"grwin_chk\":12
,\"grlost_chk\":3,\"grwinpr_chk\":\"0.714\"}","ordering":"1","logo":"https:\/\/api.stat
orium.com\/media\/bearleague\/bl15807219791504.png"}

React Native Form only submitting one value at a time

When I submit a form to my api, its weirdly only sending the last input that I filled out on the form. I have all of my form attributes saved to a const object and then sent with an axios post request. This is my first react native app, I don't know what's the cause of this issue. I have another form that doesn't have nested attributes, but saves without issue. How can I send all form inputs together in one api call with my nested form object?
SERVER LOGS
Started POST "/api/v1/applicant_forms" for 127.0.0.1 at 2021-05-02 13:08:14 -0400
Processing by Api::V1::ApplicantFormsController#create as JSON
Parameters: {"applicant_form"=>{"user_id"=>"11", "personal_info_attributes"=>{"prefix"=>"Mr"}}}
ApplicantForm.js
handleSubmit(e) {
e.preventDefault();
const {applicant_form: {personal_info_attributes: {prefix, first_name}}, user_id} = this.state;
const data_obj = {
applicant_form: {
user_id,
personal_info_attributes: {
prefix,
first_name
}
}
}
const { navigation } = this.props;
return axios({
url: `http://127.0.0.1:3000/api/v1/applicant_forms`,
method: 'POST',
data: data_obj,
}).then(response => {
console.log("Successful Response" + response)
navigation.navigate('home')
}).catch(err => {
showMessage({
message: "Something went wrong!",
description: "Testing",
type: 'danger'
})
})
}
render() {
return(
<KeyboardAvoidingView behavior="padding">
<View style={{paddingVertical: 5, paddingHorizontal: 14}}>
<View style={{backgroundColor: '#fff', width: Dimensions.get('window').width * 0.9, minHeight: 50, padding: 2, borderColor: 'gray', borderRadius: 4, borderWidth: 1, height: Dimensions.get('window').height * 0.8}}>
<View style={styles.centerText}>
<Text>Applicant Profile</Text>
</View>
<ScrollView>
<Text>Prefix</Text>
<FormInput
inputStyle={styles.input}
autoCapitalize="none"
onSubmitEditing={() => this.applicant_form.personal_info_attributes.prefix}
autoCorrect={false}
keyboardType='default'
returnKeyType="next"
placeholder='Prefix: Mr. Mrs. Ms., etc'
onChangeText={prefix => this.setState({ applicant_form: {personal_info_attributes: {prefix: prefix} }})}
// value={this.state.applicant_form.personal_info_attributes.prefix}
/>
<Text>First Name</Text>
<FormInput
inputStyle={styles.input}
autoCapitalize="none"
onSubmitEditing={() => this.applicant_form.personal_info_attributes.first_name}
autoCorrect={false}
keyboardType='default'
returnKeyType="next"
placeholder='First Name'
onChangeText={first_name => this.setState({ applicant_form: {personal_info_attributes: {first_name: first_name} }})}
// value={this.state.applicant_form.personal_info_attributes.first_name}
/>
<TouchableOpacity style={styles.saveButtoncontainer} onPress={e=>{this.handleSubmit(e)}}>
<Text style={styles.buttontext}>Save Employment Profile</Text>
</TouchableOpacity>
</View>
</View>
</KeyboardAvoidingView>
)
You are overwriting the applicant_form value every-time that a text field is edited.
The following code replaces the content in the state applicant_form to be {personal_info_attributes: {prefix: prefix} }. If you had set first_name before, it'll get removed.
<FormInput
...
onChangeText={prefix => this.setState({ applicant_form: {personal_info_attributes: {prefix: prefix} }})}
/>
To prevent this overwriting the object, you can use the spread operator to make sure that the values are cloned and updated accordingly.
<FormInput
onChangeText={prefix =>
this.setState(prevState => ({
applicant_form: {
...prevState.applicant_form,
personal_info_attributes: {
...prevState.applicant_form.personal_info_attributes,
prefix: prefix,
}
}
}))
}
/>
You can read more about this here: What's the best alternative to update nested React state property with setState()?

How can I update text of dynamic component on react native?

I´m new to react and react-native, I want to show a component that is composed of:
so when the user checks the corresponding checkbox I transform the mentioned component adding another view getting something like this:
The problem comes when the user clicks on the Text element because I show a modal to pick the desired hour and minutes and when this modal closes I'm pretending to update the state and this updates the Text element with the selected time but it´s not working, any advice?
this is my code:
import React from 'react';
import {View,Text, TextInput, StyleSheet,TouchableOpacity} from 'react-native';
import { CheckBox } from 'react-native-elements';
import DateTimePicker from 'react-native-modal-datetime-picker';
let frmHoras;
export default class CustomChkHorario extends React.Component{
constructor(props){
super(props);
this.state={
chk:false,
fontColor:'black',
title:'Closed',
isDateTimePickerVisible: false,
sTimeMonday:'00:00',
eTimeMonday:'00:00'
}
}
_showDateTimePicker = () => {
this.setState({ isDateTimePickerVisible: true });
}
_hideDateTimePicker = () => this.setState({ isDateTimePickerVisible: false });
_handleDatePicked = (date) => {
console.log('A date has been picked: ', date);
this.setState({sTimeMonday:date});
this._hideDateTimePicker();
};
pressedChk = () => {
//console.log('checked:',this.state.checked);
this.setState({chk:!this.state.chk}, () =>{
if(this.state.chk==false){
this.setState({fontColor:'black', title:'Closed'});
frmHoras=null;
}else{
this.setState({fontColor:'green', title:'Open'});
frmHoras=
<View style={{flexDirection:'row',alignItems:'center'}}>
<Text>from:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}>{this.state.sTimeMonday}</Text>
</TouchableOpacity>
<Text>to:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}></Text>
</TouchableOpacity>
</View>;
}
});
}
render(){
return(
<View style={{alignItems:'center'}}>
<View style={{flexDirection:'row',justifyContent:'center',alignItems:'center'}}>
<Text>{this.props.dia}</Text>
<CheckBox title={this.state.title}
checked={this.state.chk}
onPress={this.pressedChk}
checkedColor='green'
textStyle={{color:this.state.fontColor}}></CheckBox>
</View>
<View>
{frmHoras}
</View>
<DateTimePicker
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this._handleDatePicked}
onCancel={this._hideDateTimePicker}
mode={'time'}
/>
</View>
);
}
}
const styles = StyleSheet.create({
input: {
marginHorizontal: 10,
height:25,
width:60,
borderBottomColor:'black',
borderStyle:'solid',
borderBottomWidth:1,
margin:10
}
});
_handleDatePicked = date => {
const time = new Date(date);
const timePicked = `${time.getHours()}:${time.getMinutes()}`;
this.setState({ sTimeMonday: timePicked });
this._hideDateTimePicker();
};
pressedChk = () => {
this.setState({ chk: !this.state.chk }, () => {
if (this.state.chk) {
this.setState({ fontColor: 'green', title: 'Open' });
} else {
this.setState({ fontColor: 'black', title: 'Closed' });
}
});
};
render() {
return (
<View style={{ alignItems: 'center' }}>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text>{this.props.dia}</Text>
<CheckBox
title={this.state.title}
checked={this.state.chk}
onPress={this.pressedChk}
checkedColor="green"
textStyle={{ color: this.state.fontColor }}
/>
</View>
{this.state.chk && (
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text>from:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}>{this.state.sTimeMonday}</Text>
</TouchableOpacity>
<Text>to:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input} />
</TouchableOpacity>
</View>
)}
<DateTimePicker
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this._handleDatePicked}
onCancel={this._hideDateTimePicker}
mode={'time'}
/>
</View>
);
}
}
You should render frmHoras in a function, but you are currently doing that in the setState callback, which is a bit misleading in your case, as setState callback is called when setState is completed and the component is re-rendered. Look at the document which clearly mentioned about this behaviour
The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered.
So, changes will as follows
Create a new function which will render frmHoras, let it be renderFrmHoras
renderFrmHoras = () => {
const { chk } = this.state;
if(!chk) {
return null;
}
return (
<View style={{flexDirection:'row',alignItems:'center'}}>
<Text>from:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}>{this.state.sTimeMonday}</Text>
</TouchableOpacity>
<Text>to:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}></Text>
</TouchableOpacity>
</View>;
);
}
Next, update the pressedChk to set fontColor, title and chk values
pressedChk = () => {
this.setState((prevState) => {
return ({
chk: !prevState.chk,
fontColor: !prevState.chk ? 'green' : 'black',
title: !prevState.chk ? 'Open' : 'Closed'
});
})
}
Next, in the render method, just call the renderFrmHoras function
render() {
return (
...
</View>
<View>
{this.renderFrmHoras()}
</View>
<DateTimePicker
...
/>
...
);
}
Hope this will help!

Image is not displaying after loading from database?

I'm quite new to react native. I have a user with a profile picture that I'm trying to display on screen, when printing to my console snapshot.val().imageURL the correct url is displayed using this:
var profImage = 'https://www.placeholdit.com';
var user = authFB.currentUser;
if (user) {
database.ref('users').child(user.uid).once('value')
.then((snapshot) => profImage = snapshot.val().imageURL)
.catch(error => console.log(error))
} else {
console.log("No user")
}
I assign that url to profImage and try to set my image uri to that variable:
<Avatar
large
rounded
source={{ uri: profImage }}
onPress={() => alert(profImage)}
activeOpacity={0.7}
containerStyle={{ marginBottom: 12 }}
/>
However, my image container remains blank. Does this have to do that when the render function is run, the url hasn't been retrieved thus the component display is blank? Do I use this.setState to update the component? If so, what is the proper way to do so?
Here is the relevant part of my component:
class Profile extends React.Component {
static navigationOptions = {
title: "Profile",
headerStyle: {
backgroundColor: '#fff',
borderBottomWidth: 0,
},
headerTitleStyle: {
color: 'black'
},
}
constructor() {
super();
this.state = {
image: null,
uploading: null,
}
}
render() {
const { navigate } = this.props.navigation;
let { image } = this.state;
var profImage = 'https://www.placeholdit.com';
var user = authFB.currentUser;
if (user) {
database.ref('users').child(user.uid).once('value')
.then((snapshot) => profImage = snapshot.val().imageURL)
.catch(error => console.log(error))
} else {
console.log("No user")
}
return (
<ScrollView>
<View style={styles.profileTopContainer}>
<Avatar
large
rounded
source={{ uri: img }}
onPress={() => alert(profImage)}
activeOpacity={0.7}
containerStyle={{ marginBottom: 12 }}
/>
<Text
style={styles.usernameText}
>
Jordan Lewallen
</Text>
<TouchableHighlight
onPress={this._pickImage}>
<Text
style={styles.userMinutes}
>
Choose a profile picture
</Text>
</TouchableHighlight>
{this._maybeRenderImage()}
{this._maybeRenderUploadingOverlay()}
{
(image)
? <Image source={{ uri: image }} style={{ width: 250, height: 250 }} />
: null
}
</View>
}
please try this
<Avatar
large
rounded
source={{ uri: img }}
onPress={() => alert(profImage)}
activeOpacity={0.7}
containerStyle={{ marginBottom: 12 }}
/>
replace with
<Avatar
large
rounded
source={{ uri: profImage }}
onPress={() => alert(profImage)}
activeOpacity={0.7}
containerStyle={{ marginBottom: 12 }}
/>
This is because you call the async request inside your render method itself.
When your render method execute you request for imageUrl which is a async call and takes time to resolve and update the value of profImage variable. At that time your render method is finished its execution and set the placeholder.
If you need this to be done you should keep this profImage in your component state. So once the state is updated your render method will be called again and update the UI with new image.
Try this!
class Profile extends React.Component {
static navigationOptions = {
title: "Profile",
headerStyle: {
backgroundColor: '#fff',
borderBottomWidth: 0,
},
headerTitleStyle: {
color: 'black'
},
}
constructor() {
super();
this.state = {
image: null,
uploading: null,
}
}
componentWillRecieveProps(nextProps){
var profImage = 'https://www.placeholdit.com';
var user = authFB.currentUser;
if (user) {
database.ref('users').child(user.uid).once('value')
.then((snapshot) => this.setState({ image: snapshot.val().imageURL }))
.catch(error => console.log(error))
} else {
this.setState({ image: 'https://www.placeholdit.com' });
console.log("No user")
}
}
render() {
const { navigate } = this.props.navigation;
let { image } = this.state;
return (
<ScrollView>
<View style={styles.profileTopContainer}>
<Avatar
large
rounded
source={{ uri: image }}
onPress={() => alert(profImage)}
activeOpacity={0.7}
containerStyle={{ marginBottom: 12 }}
/>
<Text
style={styles.usernameText}
>
Jordan Lewallen
</Text>
<TouchableHighlight
onPress={this._pickImage}>
<Text
style={styles.userMinutes}
>
Choose a profile picture
</Text>
</TouchableHighlight>
{this._maybeRenderImage()}
{this._maybeRenderUploadingOverlay()}
{
(image)
? <Image source={{ uri: image }} style={{ width: 250, height: 250 }} />
: null
}
</View>
}

How to pass form data to another page in react native?

I've created a login page like this:
class Login extends Component {
render() {
const { navigate } = this.props.navigation
return (
<View style={{ flex: 1 }}>
<View style={styles.container}>
<View style={styles.container1}>
<TextInput
style={{ width: 190, color: 'white' }}
placeholder="User Name"
placeholderTextColor="#f9f9f9"
underlineColorAndroid="#f9f9f9"
/>
<TextInput
placeholder="Password"
secureTextEntry
returnKeyType="go"
ref={input => (this.passwordInput = input)}
style={{ width: 190, color: 'white' }}
placeholderTextColor="#f9f9f9"
underlineColorAndroid="#f9f9f9"
/>
<TouchableOpacity style={{ top: 10 }}>
<Button
color="#314561"
onPress={() => navigate('HomePage')}
title="Login"
/>
</TouchableOpacity>
</View>
</View>
</View>
)
}
}
export default Login
Now I need to pass the username to the home page. I've referred a number of resources and didn't got any solutions. How can I pass the username to home page?
First save your input value to some variables using onChangeText
<TextInput
value= {this.state.userName}
onChangeText = {(text)=>{
this.setState({userName:text});
}
/>
Then you can pass the value ,
<Button
onPress={() => navigate('HomePage',{"userName":this.state.userName})} // you can pass objects
title="Login"
/>
Do the following changes :
In Login component :
Username Field
<TextInput
style={{width:190,color:'white'}}
placeholder="User Name"
placeholderTextColor="#f9f9f9"
underlineColorAndroid='#f9f9f9'
onChangeText=
{(username)=>this.setState({username})}
/>
Button :
<TouchableOpacity style={{top:10}}>
<Button
color="#314561"
onPress={() => navigate('HomePage'), { username: this.state.username }}
title="Login"/>
</TouchableOpacity>
In Home component:
e.g. render method
render(){
const {state} = this.props.navigation;
console.og(state.params.username)
}
Update :
In login constructor,initialise state
constructor(){
super();
this.state = {};
}
class Login extends Component {
constructor(props) {
super(props);
this.state = {
userName:"",
password:""
};
}
updateUserName = (name) =>{
this.setState({
userName:name,
})
}
updatePwd = (pwd) =>{
this.setState({
password:pwd,
})
}
render() {
const { navigate } = this.props.navigation
return (
<View style={{ flex: 1 }}>
<View style={styles.container}>
<View style={styles.container1}>
<TextInput
style={{ width: 190, color: 'white' }}
placeholder="User Name"
placeholderTextColor="#f9f9f9"
underlineColorAndroid="#f9f9f9"
onChangeText={(name) => this.updateUserName(name)}
value={this.state.userName}
/>
<TextInput
placeholder="Password"
secureTextEntry
returnKeyType="go"
ref={input => (this.passwordInput = input)}
style={{ width: 190, color: 'white' }}
placeholderTextColor="#f9f9f9"
underlineColorAndroid="#f9f9f9"
onChangeText={(pwd) => this.updatePwd(pwd)}
value={this.state.password}
/>
<TouchableOpacity style={{ top: 10 }}>
<Button
color="#314561"
onPress={() => navigate('HomePage',{userName:this.state.userName})}
title="Login"
/>
</TouchableOpacity>
</View>
</View>
</View>
)
}
}
export default Login
file : homePage.js
constructor(props) {
super(props);
const { params } = this.props.navigation.state;
var data = params.userName;
this.state = {
userName : data
};
}

Resources