0

My first React project. What I want to do is to first display the logo and then check if the user is logged in. If they are they go straight to next page. If not the login form appears below the logo in the same page. Similar to how the Facebook app works when you open it.

What i got so far using Firebase for auth:

  loginCheck(){
    const { navigate } = this.props.navigation;
    firebase.auth().onAuthStateChanged(function(user) {
      if (user) {
        navigate('Feed');
      } else {
        return (
          <View style={styles.formContainer}>
            <FormLabel>Email</FormLabel>
            <FormInput
            onChangeText={(email) => this.setState({ email })}/>
            <FormLabel>Password</FormLabel>
            <FormInput
             secureTextEntry
            onChangeText={(password) => this.setState({ password })}/>
            <Text style={styles.statusText}>{ this.state.error }</Text>
            {this.renderButtonOrLoading()}
          </View>
        )
      }
    });
  }

  render() {
    return (
      <KeyboardAvoidingView behavior="padding" style={styles.container}>
        <View style={styles.loginContainer}>
          <Image resizeMode="contain" style={styles.logo} source={require('../../components/images/logo.png')} />
        </View>
        {this.loginCheck()}
      </KeyboardAvoidingView>
    );
  }
}

Aim is to get everything in the return statement of loginCheck() to show in render if user is not logged in. I know my approach is wrong, just don’t know how to go about fixing it.

The renderButtonOrLoading() seems to work fine, however, when I replace {this.loginCheck()} in render() with everything in the return statement of loginCheck().

  renderButtonOrLoading(){
    if(this.state.loading){
      return (<Text style={styles.statusText}>Loading</Text>);
    }
    return (
      <View>
        <Button
        onPress={this.onLoginPress.bind(this)}
        title='Login'/>
        <Button
        onPress={this.onSignupPress.bind(this)}
        title='Sign Up'/>
      </View>
    );
  }

Would appreciate any help, been stuck on this problem for a while.

Lypyrhythm
  • 324
  • 2
  • 13
user3458571
  • 73
  • 1
  • 2
  • 7

2 Answers2

1

My guess would be that your call to firebase.auth().onAuthStateChanged() is not completing in time for render - i.e. you invoke the Promise but it doesn't resolve before render gets called. If you make a call to setState inside the .then() block of that promise, you will at least trigger a re-render, but that still means you're making a new request for auth on every call to render. My suggestion would be to move your auth check to componentDidMount:

componentDidMount() {
    firebase.auth().onAuthStateChanged(function(user) {
        if (user) {
            this.setState({ isAuthorized: true });
        } else {
            this.setState({ isAuthorized: false });
    });
}

And then just use the ternary operator in render to determine which UI to show:

render() {
    ...your base code
    {this.state.isAuthorized ? navigate('Feed') : <Your Login UI>}
}

You may also check out this library - auth state is persisted across app restarts/boots: https://github.com/invertase/react-native-firebase Best of luck!

Parker Ziegler
  • 980
  • 6
  • 13
  • Seem to be getting an error. this.setState' is undefined. – user3458571 Nov 11 '17 at 18:05
  • So i can confirm this seems like the correct approach, If i manually set the states I am getting the correct outcome so thanks for that! Now i think i need to do some sort of binding in the firebase auth function. I just dont know how to.. – user3458571 Nov 11 '17 at 18:57
  • How is your `firebase` object coming in? You need to make sure it is initialized to work with your Firebase account. The best way is to initialize your `firebase` in your app's entry point and then pass it as a `prop` to child components that need them. Check your `Network` requests to make sure it's sending off a request and getting something back! And please up vote the answer if you think it would be helpful to others! – Parker Ziegler Nov 11 '17 at 19:33
  • That was all handled already. But I figured out the solution. make sure to add a .bind(this) right after right after the closing curly brackets from .onAuthStateChanged like in this solution:https://stackoverflow.com/questions/38226238/firebase-login-with-react-components – user3458571 Nov 12 '17 at 03:09
  • Hey I put this in a splash screen and if the user logged i navigate hem to Home screen, and its work fine But when I create user used createUserWithEmailAndPassword() in then() statement i want to navigate the user to a confirmation screen but it does not navigate me, it navigate to Home directly How can i handle it? – Oliver D Nov 28 '19 at 13:48
0
componentDidMount() {
      firebase.auth().onAuthStateChanged(user => {
        this.props.navigation.navigate(user ? 'Screen One' : 'Screen Two')
      })
    }

You can directly apply this check on your First page. Here you will check you users login state and if he is logged in you can proceed