Josh Simon
Josh Simon

Reputation: 259

Firebase auth, React: Auth sporadically failing

I have a component GigRegister - one of it's functions is to get all the documents from a collection, and return only the documents created by the currently logged in user:

      authListener() {
        auth().onAuthStateChanged(user => {
          if(user){
            this.setState({
              userDetails:user
            },
            () =>
            firebase.firestore().collection('gig-listing').onSnapshot(querySnapshot => {
              let filteredGigs = querySnapshot.docs.filter(snapshot => {
                return snapshot.data().user === this.state.userDetails.uid
              })
              this.setState({
                filterGigs: filteredGigs
              })
            })
            ) //end of set state
          } else {
            this.setState({
              userDetails:null
            })
            console.log('no user signed in')
          }
        })
      }

      componentDidMount() {
        this.authListener();
      }

Another function of this component is to capture data from the user and then post it to firebase, after which it redirects to another component.

      handleSubmit(e) {
        
        let user = auth().currentUser.uid;
        const gigData = {
          name: this.state.name,
          venue: this.state.venue,
          time: this.state.time,
          date: this.state.date,
          genre: this.state.genre,
          tickets: this.state.tickets,
          price: this.state.price,
          venueWebsite: this.state.venueWebsite,
          bandWebsite: this.state.bandWebsite,
          user: user
        };

        auth()
          .currentUser.getIdToken()
          .then(function (token) {
            axios(
              "https://us-central1-gig-fort.cloudfunctions.net/api/createGigListing",
              {
                method: "POST",
                headers: {
                  "content-type": "application/json",
                  Authorization: "Bearer " + token,
                },
                data: gigData,
              }
            );
          })
          .then((res) => {
            this.props.history.push("/Homepage");
          })
          .catch((err) => {
            console.error(err);
          });
      }

So here's the issue. Sometimes this component works as it should, and the data submit and redirect work as intended. Occasionally though, I'll hit submit but trigger the message TypeError: Cannot read property 'uid' of null . Interestingly, the post request is still made.

I've been logged in both when it succeeds and fails, and I can only assume that this.state.userDetails.uid evaluating to null means that auth state has expired, or that the component is rendering before userDetails can be assigned a value?
The issue I have is that I can't tell if this is an async problem, or an auth state persistence problem, and I also can't figure why it's a sporadic failure.

Upvotes: 0

Views: 42

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317497

This line of code might be causing you trouble:

let user = auth().currentUser.uid;

currentUser will be null if there is no user signed in at the time it was accessed (or it's not known for sure if that is the case). This is covered in the API documentation.

Ideally, you should never use currentUser, and instead rely on the state provided by onAuthStateChanged. I talk about this in detail in this blog post. If you do need to use currentUser, you should check it for null before referencing properties on it.

You should also know that getting an ID token is best done by using a listener as well. The call is onIdTokenChanged, and it works like the auth state listener.

Keep in mind also that setState is asynchronous and doesn't set the state immediately. It's possible that your Firestore query isn't getting the state it needs immediately.

Upvotes: 1

Related Questions