Search code examples
reactjsfirebasefirebase-authenticationreact-router-domreact-redux-firebase

React with react-redux-firebase isLoaded is true and isEmpty is seemingly false, yet firebase.auth().currentUser is null - what could be the cause?


so I might have difficulty explaining this issue I am having, which I am not able to reproduce consistently. I have a React app on which I am using react-redux-firebase and that I thought I was successfully implementing to keep track of the user session.

My App.js file has the following bit or routing code as a sample (using react-router-dom):

<Route
    path="/signin"
    render={() => {
        if (!isLoaded(this.props.auth)) {
            return null;
        } else if (!isEmpty(this.props.auth)) {
            return <Redirect to="/posts" />;
        }
        return <Signin />;
    }}
/>

This works correctly. I go to Signin component when user is not logged in or Posts when user is logged in. In Signin component I have this bit of logic that happens:

        // sign the user in
        this.props.firebase.login({
            email: user.email,
            password: user.password
        }).then(response => {

            // detect the user's geolocation on login and save
            if (isLoaded(this.props.auth)) {
                const navigator = new Navigator();
                navigator.setGeoLocation(this.props.firebase);
            }

            // redirect user to home or somewhere
            this.props.history.push('posts');
            
        })

I am importing isLoaded like so:

import { firebaseConnect, isLoaded } from 'react-redux-firebase';

the condtional works fine, the user is logged in and then the isLoaded conditional happens - this is where the problem arises. With isLoaded true I would assume that the user and all the redux-firestore user properties are ready for use....but that is sometimes not the case. In navigator.setGeoLocation call I have this:

setGeoLocation(propsFirebase, cb) {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition((position) => {
            propsFirebase.auth().currentUser
                .getIdToken(/* forceRefresh */ true)
                .then((idToken) => {
                    ...
                });
            }
        )
    }
}

At this point, propsFirebase.auth().currentUser is sometimes null (this originates in the parameter passed in navigator.setGeoLocation(this.props.firebase);). If I try the signin in all over again, then it works. I am not able to find any consistent way of reproducing.

I have noticed this in other components too. I am not sure if this is an issue that happens when my computer goes to sleep and I should restart the whole React process or what? has anyone seen similar issues? If so, what could I possibly be missing during checking user state in the routing?

If more code is necessary, let me know...


Solution

  • currentUser will be null with the user is not signed in. It will also be null when a page first loads, before the user's token has been loaded and a User object is available. You should use an auth state observer to get the User object if you want to act immediately after it is loaded asynchronously after page load.

    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        // User is signed in, see docs for a list of available properties
        // https://firebase.google.com/docs/reference/js/firebase.User
        var uid = user.uid;
        // ...
      } else {
        // User is signed out
        // ...
      }
    });
    

    You might also want to read for more detail: Why is my currentUser == null in Firebase Auth?