I'm working on a personal project and I have trouble with checking if a user is logged in or not so that when they try to go to /login, it'll redirect them to the home page. Currently what my code does is the following:
- Defined my own Route components
- When checkIfSignedIn is called, it dispatches actions that set the isLoggedIn state to either True or False.
- The AuthenticatedRouter component checks if the store's isLoggedIn state is true or false and will either render the component or redirect to home.
- This works, but the issue is that isLoggedIn is initially false, so if they are logged in, the login form shows up for a second and then redirects after isLoggedIn becomes true.
I can't figure out how to fix the problem with rendering the component with the default state and then suddenly redirects because the state changes. Thanks
- I'm using firebase for the user account.
Routes.js
const Routes = (props) => {
props.checkIfSignedIn();
return(
<Router>
<Switch>
<Route exact path='/' component={App}/>
<AuthorizedRoute path="/signup" component={SignUp}/>
<AuthorizedRoute path="/signin" component={SignIn}/>
<Route component={InvalidPage}/>
</Switch>
</Router>
);
};
const mapDispatchToProps = (dispatch) => {
return{
checkIfSignedIn: () => dispatch(checkIfSignedIn())
};
};
export default connect(null, mapDispatchToProps)(Routes);
AuthorizedRoute.js
class AuthorizedRoute extends React.Component{
constructor(props){
super(props);
this.state = {
isLoggedIn: false
};
};
render(){
const { component: Component, ...rest } = this.props;
return(
<Route {...rest} render={props => {
if (this.props.isLoggedIn){
console.log(this.state.isLoggedIn);
return <Redirect to="/" />
} else{
return <Component {...props} />
}
}} />
);
}
};
const mapStateToProps = (state) => {
return{
isLoggedIn : state.authentication.isLoggedIn
};
};
export default connect(mapStateToProps, null)(AuthorizedRoute);
authentication.js - action creators
const setSignedInFalse = () => {
return{
type: IS_SIGNED_IN_FALSE
};
};
const setSignedInTrue = () => {
return{
type: IS_SIGNED_IN_TRUE
};
};
const checkIfSignedIn = () => {
return dispatch => {
firebaseApp.auth().onAuthStateChanged(user => {
if (user){
dispatch(setSignedInTrue());
} else{
dispatch(setSignedInFalse());
}
});
};
};
export default checkIfSignedIn;
authentication.js - reducer
const defaultState = {
isLoggedIn: false
};
const authentication = (state = defaultState, action) => {
let authenticationState = null;
switch (action.type){
case IS_SIGNED_IN_FALSE:
authenticationState = {
isLoggedIn: false
};
return authenticationState;
case IS_SIGNED_IN_TRUE:
authenticationState = {
isLoggedIn: true
};
return authenticationState;
default:
return state;
};
};
export default authentication;
Hacky solution (Not sure if this is frowned upon).
I set my Auth reducer's default state, isLoggedIn : null instead of false. Then in my AuthorizedRoute component I now have 3 conditions to render null first and then either the component or redirect.
//AuthorizedRoute Component
if (this.props.isLoggedIn){
return <Redirect to="/" />
} else if (this.props.isLoggedIn === false){
return <Component {...props} />
} else{
return null;
}