最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - React Native - Displaying a Loading Screen Component in a Javascript Promise - Stack Overflow

programmeradmin4浏览0评论

In the code below (in auth_shared.js), I have a Loading ponent that I wish to display when the promises signInWithEmailAndPassword() or createUserWithEmailAndPassword() 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 to false initially. In render(), I then check the value of isLoading and determine if I should load the Loading ponent or the Log in or Sign up fields. If signInWithEmailAndPassword() is called I then set isLoading = true in an attempt to display the Loading ponent while the promise is validating the users email and password. 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: ''
    }
  }

  ponentDidMount() {
    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');
    }
  }
}

In the code below (in auth_shared.js), I have a Loading ponent that I wish to display when the promises signInWithEmailAndPassword() or createUserWithEmailAndPassword() 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 to false initially. In render(), I then check the value of isLoading and determine if I should load the Loading ponent or the Log in or Sign up fields. If signInWithEmailAndPassword() is called I then set isLoading = true in an attempt to display the Loading ponent while the promise is validating the users email and password. 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: ''
    }
  }

  ponentDidMount() {
    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');
    }
  }
}
Share Improve this question edited Aug 5, 2016 at 3:47 szier asked Aug 5, 2016 at 3:19 szierszier 1,5073 gold badges19 silver badges32 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 4

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/ponent-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;
        }
      });
  }
发布评论

评论列表(0)

  1. 暂无评论