Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native - Redirect logged in Firebase user to Home Component

My goal is to redirect the user to the Home component if the user is already logged in. I am able to login a user and redirect them to Home only if _logInUser() is called. However, once redirected to the Home component, if I refresh the simulator the app goes back to the Login component.

I attempted to solve this using componentWillMount() and setting let user = firebaseApp.auth().currentUser. However, I even logged the user to the console but it seems like the if check goes straight to the else statement. I would appreciate any insight!

Here is my code (I am using react-native-router-flux for routing):

index.ios.js

import React, { Component } from 'react';
import { Scene, Router } from 'react-native-router-flux';
import {
  AppRegistry,
} from 'react-native';

// Components
import Login from './components/user/login/login';
import Home from './components/user/home/home';

class AppName extends Component {
  render() {
    return (
      <Router>
        <Scene key="root">
          <Scene key="login" component={Login} title="Login" hideNavBar={true} initial={true}/>
          <Scene key="home" component={Home} title="Home"/>
        </Scene>
      </Router>
    );
  }
}


AppRegistry.registerComponent('AppName', () => AppName);

login.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 'AppName/firebase_setup';

// Set width and height to screen dimensions
const { width, height } = Dimensions.get("window"); 

// For Firebase Auth
const auth = firebaseApp.auth();

// Removed styles for StackOverflow

export default class Login extends Component {
  constructor(props) {
    super(props);

    this.state = {
      email: '',
      password: ''
    }
  }

  componentWillMount() {
    let user = auth.currentUser;
    if (user != null) {
      console.log(user);
      Actions.home
    } else {
      return;
    }
  }

  render() {
    return (
      <View style={styles.mainContainer}>
        <KeyboardAwareScrollView 
          style={styles.scrollView}
          keyboardShouldPersistTaps={false}
          automaticallyAdjustContentInsets={true}
          alwaysBonceVertical={false}
        >
          <View style={styles.loginContainer}>

            <View style={styles.inputContainer}>

              <TextInput
                style={styles.formInput}
                placeholder="Email"
                keyboardType="email-address"
                autoFocus={true}
                autoCorrect={false}
                autoCapitalize="none"
                onChangeText={(email) => this.setState({email})}
              />

              <TextInput
                style={styles.formInput}
                secureTextEntry={true}
                placeholder="Password"
                autoCorrect={false}
                autoCapitalize="none"
                onChangeText={(password) => this.setState({password})}
              />

              <TouchableOpacity 
                style={styles.loginButton}
                onPress={this._logInUser.bind(this)}
              >
                <Text style={styles.loginButtonText}>Log In</Text>
              </TouchableOpacity>

              <TouchableOpacity>
                <Text style={styles.toSignupButton}>Dont have an account? Create one!</Text>
              </TouchableOpacity>

            </View>
          </View>

          <View style={styles.footer}>
            <Text style={styles.footerText}>
              By signing up, I agree to TextbookSwap's <Text style={styles.footerActionText}>Terms of Service</Text> and <Text style={styles.footerActionText}>Privacy Policy</Text>.
            </Text>
          </View>
        </KeyboardAwareScrollView>
      </View>
    );
  }

  _logInUser() {
    let email = this.state.email;
    let password = this.state.password;

    auth.signInWithEmailAndPassword(email, password)
      .then(Actions.home)
      .catch((error) => {
        AlertIOS.alert(
          `${error.code}`,
          `${error.message}`
        );
      });
  }
}
like image 680
szier Avatar asked Jul 31 '16 18:07

szier


1 Answers

First, in your login component you are checking currentUser in synchronous way, but it might be not yet available at componentWillMount. You can should get in asynchronously:

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // No user is signed in.
  }
});

Most likely it will be enough to call Actions.home() if user is logged in. However, as your app grows you might want to move this logic up from Login screen. As Kyle suggested, you can use Switch feature. It is usually (to quote docs) used with redux, like this:

const RootSwitch = connect(state => ({loggedIn: state.transient.loggedIn}))(Switch);
const rootSelector = props => props.loggedIn ? 'workScreens' : 'authScreens';

const scenes = Actions.create(
   <Scene key="root" tabs={true} component={RootSwitch} selector={rootSelector}>
     <Scene key="authScreens" hideNavBar={true}>
       <Scene key="login" component={Login} initial={true}/>
       <Scene key="register" component={Register} />
       ...
     </Scene>
     <Scene key="workScreens">
       <Scene key="home" component={Home} initial={true}/>
       <Scene key="profile" component={ProfileMain}/>
       ...
     </Scene>
   </Scene>
);

If you don't want to use redux, you can manually wrap Switch instead of using react-redux's connect and pass loggedIn prop to Switch. For example, you can listen to firebase onAuthStateChanged in this wrapper, something like this:

class FirebaseSwitch extends Component {

  state = {
    loggenIn: false
  }

  componentWillMount() {
    firebase.auth().onAuthStateChanged( user =>
      this.setState({loggedIn: !!user})
    );
  }

  render() {
    return <Switch loggedIn={this.state.loggedIn} {...this.props}/>;
  }
}
like image 158
Konstantin Kuznetsov Avatar answered Nov 15 '22 23:11

Konstantin Kuznetsov