Dispatch an action before rendering in react native redux?

I'm trying to log user in with firebase authentication and I ran into this problem that when I use onAuthStateChanged method in action creator to get is user logged in before or not. When users is logged in before so I just call login success and navigate them to main screen, if not I just dispatch another action and show login screen, but I still see login screen for like half a second if login success action dispatched, I'm new to react native and redux, can anyone help me solve this issue, thank you guys so much!!

here is my index.js

import { checkLogin } from './actions';

class LoginScreen extends Component {
  componentDidMount() {
    this.props.checkLogin();
  }

  componentWillReceiveProps(nextProp) {
    if (nextProp.loggedIn) {
      this.props.navigation.navigate('main');
    }
  }

  //... some code

  render() {
    if (this.props.isChecking) {
      return <Spinner />
    }
    return this.renderContent();
  }
}

const mapStateToProps = ({ auth }) => {
  const { email, password, error, loading, loggedIn, isChecking } = auth;
  return { email, password, error, loading, loggedIn, isChecking }; 
};

export default connect(mapStateToProps, { 
  emailChanged, passwordChanged, emailLogin, checkLogin 
})(LoginScreen);

and here is my actions.js

import firebase from 'firebase';

export const checkLogin = () => {
  return(dispatch) => {
    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        dispatch({ type: EMAIL_LOGIN_SUCCESS, payload: user });
      } else {
        dispatch({ type: CHECK_LOGIN_FAILED });
      }
    })
  }
}

// some code

and reducer.js

const INITIAL_STATE = { 
  // ...
  isChecking: true,
}

export default (state = INITIAL_STATE, action) => {
  console.log(action);
  switch (action.type) {
    // ...
    case CHECK_LOGIN_FAILED:
      return { ...state, isChecking: false };
    case EMAIL_LOGIN_SUCCESS:
      return { ...state, user: action.payload, error: '', loading: false, email: '', password: '', loggedIn: true, isChecking: false };
    default: 
      return state;
  }
}

1 answer

  • answered 2017-11-13 03:11 jkurs

    I think this happens because the previous state of isChecking is remembered by your reducer from the previous rendering of your component. I bet if you reset the content and settings of your simulator that you would not first see the login page. However, to fix this I would recommend dispatching an action before firebase.auth().onAuthStateChanged to tell your reducer that you are in an "isChecking" state.