React Native - Displaying a Loading Screen Component in a Javascript Promise
In your constructor you should set isLoading
to false
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true, // change this to false
Whenever you want to show the loading indicator, you should change isLoading
to true
before the async call, not on the callback.
You should only change the state via setState
(see https://facebook.github.io/react/docs/component-api.html)
_logInUser() {
let { isLoading, email, password } = this.state;
this.setState({isLoading:true}); // move state change here
auth.signInWithEmailAndPassword(email, password)
.then(() => {
Actions.home;
this.setState({isLoading:false}); // use setState
})
.catch((error) => {
this.setState({isLoading:false}); // use setState
switch(error.code) {
case "auth/wrong-password":
AlertIOS.alert('Uh oh!', 'Invalid password! Please try again.');
break;
case "auth/invalid-email":
AlertIOS.alert('Uh oh!', 'Invalid email! Please try again.');
break;
case "auth/user-not-found":
AlertIOS.alert('Uh oh!', 'Please check your credentials and try again');
break;
}
});
}
szier
I am a Computer Science major and future Software Engineer at Lyft. I also do independent software consulting in the Bay Area to stay busy during school 😃
Updated on June 06, 2022Comments
-
szier almost 2 years
In the code below (in auth_shared.js), I have a
Loading
component that I wish to display when the promisessignInWithEmailAndPassword()
orcreateUserWithEmailAndPassword()
are called (whenever the user hits the "Log in" or "Sign up" buttons).To do this, I thought it was best to create a state called
isLoading
and set it tofalse
initially. Inrender()
, I then check the value ofisLoading
and determine if I should load theLoading
component or the Log in or Sign up fields. IfsignInWithEmailAndPassword()
is called I then setisLoading = true
in an attempt to display theLoading
component while the promise is validating the usersemail
andpassword
. However, this does not seem to work and I am not sure why! Can someone please provide some insight into this? Thank you. Here is my code:loading.js
import React, { Component } from 'react'; import { ActivityIndicator, Text, View } from 'react-native'; import styles from 'TextbookSwap/app_styles'; export default class Loading extends Component { render() { return ( <View style={styles.loadingBG}> <ActivityIndicator animating={true} color="white" size="large" style={{margin: 15}} /> <Text style={styles.loadingText}> {this.props.loadingText} </Text> </View> ); } }
login.js
import React, { Component } from 'react'; // Components import AuthShared from '../auth_shared'; export default class Login extends Component { render() { return ( <AuthShared login={true}/> ); } }
signup.js
import React, { Component } from 'react'; // Components import AuthShared from '../auth_shared'; export default class SignUp extends Component { render() { return ( <AuthShared login={false}/> ); } }
auth_shared.js
import React, { Component } from 'react'; import { AlertIOS, Dimensions, Image, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native'; import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; import { Actions } from 'react-native-router-flux'; import firebaseApp from 'TextbookSwap/firebase_setup'; import styles from 'TextbookSwap/app_styles'; // Components import HeaderImage from './header_image'; import Loading from './loading.js'; // For Firebase Auth const auth = firebaseApp.auth(); export default class Login extends Component { constructor(props) { super(props); this.state = { isLoading: true, firstName: '', lastName: '', email: '', password: '', passwordConfirmation: '' } } componentDidMount() { let user = auth.currentUser; if (user) { console.log(msg) Actions.home } else { return; } } render() { if (this.state.isLoading) { return <Loading loadingText="Loading..." /> } else { return ( <View style={styles.mainContainer}> <KeyboardAwareScrollView style={styles.scrollView} keyboardShouldPersistTaps={false} automaticallyAdjustContentInsets={true} alwaysBonceVertical={false} > <View style={styles.formInputContainer}> <HeaderImage /> {this.props.login ? this.renderLogin() : this.renderSignup()} </View> {this.props.login ? this.renderFooter() : null} </KeyboardAwareScrollView> </View> ); } } renderLogin() { return ( <View> {this.renderEmailAndPasswordForms()} <View style={styles.authButtonContainer}> <TouchableOpacity style={styles.authButton} onPress={this._logInUser.bind(this)} > <Text style={styles.actionText}>Log me in!</Text> </TouchableOpacity> </View> </View> ); } renderSignup() { return ( <View> <View style={[styles.formInputWrapper, styles.formInputInlineWrapper]}> <View style={{borderColor: '#50514F', borderLeftWidth: 0, borderRightWidth: 0.5, borderTopWidth: 0, borderBottomWidth: 0}}> <TextInput style={[styles.formInput, styles.formInputInline]} autoFocus={true} autoCapitalize="none" autoCorrect={false} placeholder="First Name" onChangeText={(firstName) => this.setState({firstName})} /> </View> <TextInput style={[styles.formInput, styles.formInputInline]} autoFocus={true} autoCapitalize="none" autoCorrect={false} placeholder="Last Name" onChangeText={(lastName) => this.setState({lastName})} /> </View> {this.renderEmailAndPasswordForms()} <View style={styles.formInputWrapper}> <TextInput style={styles.formInput} secureTextEntry={true} autoCapitalize="none" autoCorrect={false} placeholder="Password Confirmation" onChangeText={(passwordConfirmation) => this.setState({passwordConfirmation})} /> </View> <View style={styles.authButtonContainer}> <TouchableOpacity style={styles.authButton} onPress={this._signUpUser.bind(this)} > <Text style={styles.actionText}>Sign me up!</Text> </TouchableOpacity> </View> </View> ); } renderEmailAndPasswordForms() { return ( <View> <View style={styles.formInputWrapper}> <TextInput style={styles.formInput} autoFocus={true} autoCapitalize="none" autoCorrect={false} placeholder="Email" onChangeText={(email) => this.setState({email})} /> </View> <View style={styles.formInputWrapper}> <TextInput style={styles.formInput} secureTextEntry={true} autoCapitalize="none" autoCorrect={false} placeholder="Password" onChangeText={(password) => this.setState({password})} /> </View> </View> ); } renderFooter() { return ( <View style={styles.footer}> <TouchableOpacity style={styles.footerButton} onPress={Actions.signup} > <Text style={styles.actionText}>No account? Create one!</Text> </TouchableOpacity> </View> ); } _logInUser() { let { isLoading, email, password } = this.state; auth.signInWithEmailAndPassword(email, password) .then(() => { isLoading = true; Actions.home; isLoading = false; }) .catch((error) => { isLoading = false; switch(error.code) { case "auth/wrong-password": AlertIOS.alert('Uh oh!', 'Invalid password! Please try again.'); break; case "auth/invalid-email": AlertIOS.alert('Uh oh!', 'Invalid email! Please try again.'); break; case "auth/user-not-found": AlertIOS.alert('Uh oh!', 'Please check your credentials and try again'); break; } }); } _signUpUser() { let { firstName, lastName, email, password, passwordConfirmation } = this.state; // Check that email, password, and passwordConfirmation are present if (!firstName || !lastName || !email || !password || !passwordConfirmation) { AlertIOS.alert('Uh oh!', 'Please fill out all fields'); } else if (password == passwordConfirmation) { auth.createUserWithEmailAndPassword(email, password) .then((user) => { user.updateProfile({ displayName: `${firstName} ${lastName}` }) .then(Actions.home) .catch((error) => { AlertIOS.alert(`${error.code}`, `${error.message}`); }); }) .catch((error) => { AlertIOS.alert(`${error.code}`, `${error.message}`); }); } else { AlertIOS.alert('Uh oh!', 'Passwords do not match'); } } }
-
szier over 7 yearsI gave this a try and now when I hit the "Log me in!" button, the
Loading
component doesn't display. I'm thinking this is due to the fact that even thoughisLoading = true
,render()
doesn't get called again and theif
check doesn't occur to determine whether or not theLoading
component should be displayed. Do you have a solution or advice as to how I can solve this? Thank you for your help btw! -
FuzzyTree over 7 years@szier try the latest update, the problem may be because you're trying to change the state directly instead of using
setState
-
szier over 7 yearsThat worked! Just marked this as the answer. Thank you!