Reputation: 1507
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}`
);
});
}
}
Upvotes: 9
Views: 6227
Reputation: 903
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}/>;
}
}
Upvotes: 7