firebase.auth().currentUser returns null when page is refreshed

Viewed 2768

I added the function as you mentioned but when i login it shows this error:

TypeError: Cannot set property 'photo' of undefined
    at feed.page.ts:32
    at auth.esm.js:326
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
    at Object.onInvoke (core.js:17299)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:390)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:150)
    at zone.js:889
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:17290)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
    at resolvePromise (zone.js:831)
    at zone.js:896
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:17290)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
    at drainMicroTaskQueue (zone.js:601)
    at push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask (zone.js:502)
    at ZoneTask.invoke (zone.js:487)
    at timer (zone.js:2281)

If I refresh the page it says :

 getEvents() is not a function 

Changes i made and still getting the error. It is wierd because when i login and redirect toe FeedPage i get error photo of undefined, if i refresh i get getEvents() is not e function.After i refresh the photo variable is null in the feed.html and cannot be binded to the ngModel and show the photo in avatar.

events: any[] = [];
  likes: any[] = [];
  pageSize = 10;
  cursor: any; // can be declared as DocumentSnapshot
  infiniteEvent: any;
  state: any;
  private photo = '';

  // tslint:disable-next-line: max-line-length
  constructor(public navCtrl: NavController, private loadingCtrl: LoadingController, private toastCtrl: ToastController, private http: HttpClient, public actionSheetCtrl: ActionSheetController, public alertCtrl: AlertController, public modalCtrl: ModalController, public popoverCtrl: PopoverController) {

    firebase.auth().onAuthStateChanged(function (user) {
      if (user) {
        this.photo = user.photoURL;
        this.getEvents();
      } else {
        console.log('Not authenticated');
        // No user is signed in.
      }
    });
  }


  public async getEvents() {
    const loading = await this.loadingCtrl.create({
      message: 'Loading events...'
    });

    loading.present();
    const query = firebase.firestore().collection('events').orderBy('created', 'desc').limit(this.pageSize);

    query.onSnapshot((snapshot) => {
      const changedDocs = snapshot.docChanges();

      changedDocs.forEach((change) => {
        if (change.type === 'added') {
          // TODO
        }
        if (change.type === 'modified') {
          for (let i = 0; i < this.events.length; i++) {
            if (this.events[i].id == change.doc.id) {
              this.events[i] = change.doc;
            }
          }
        }
        if (change.type === 'removed') {
          // TODO
        }
      })
    })

    query.get()
      .then((events) => {

        events.forEach((event) => {
          this.events.push(event);
        });

        loading.dismiss();

        if (events.size == 0) {
          this.cursor = 0;
        } else {
          this.cursor = this.events[this.events.length - 1]; // the last index of the collection
        }
        console.log(this.events);

      }).catch((err) => {
        console.log(err);
      });
  }
2 Answers

It looks like firebase.auth().currentUser is not set when your Feed.ts runs. This is expected, since the client may need to check with the server if the token is still valid, which is an asynchronous operation.

In cases like this, always use an onAuthStateChanged listener, as shown in the first snippet in the docs on getting the current signed in user.

So something like:

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
    ... code that uses the user's properties
  } else {
    // No user is signed in.
  }
});

Edit

Your new getEvents() is not a function error is caused by the fact that this has a different meaning inside a callback function that is declared as function(). The simplest solution here is use => notation, which maintains the value of this inside the function:

firebase.auth().onAuthStateChanged((user) => {
  if (user) {
    this.photo = user.photoURL;
    this.getEvents();
  } else {
    console.log('Not authenticated');
    // No user is signed in.
  }
});

Note that the rest of your code already uses => notation, which makes me suspect that you haven't been writing JavaScript all that long yet. I highly recommend taking a tutorial in callback function in JavaScript, as it'll save you a lot of time and questions) going forward.

Ohh now i fully understand , and as exacly as you said i haven't been writing too much javascript code here, as i was watiching some tutoirals and adding some other things. I fixed the problem and also you helped me understand a basic but important thing. Thanks a lot for your time.

Related