Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firestore .startAt is not working properly

infiniteHandler($state) {
    var next = db
        .collection("posts")
        .orderBy("timestamp", "desc")
        .startAfter(this.lastVisible)
        .limit(3)

    next.get().then(documentSnapshots => {
        //Get the last visible document
        // this.lastVisible =
        // documentSnapshots.docs[documentSnapshots.docs.length - 1]

        if (documentSnapshots.docs.length == 0) $state.complete()
        else {
            this.$store.commit(
                "modules/posts/updateLastVisible",
                documentSnapshots.docs[documentSnapshots.docs.length - 1].data()
                .timestamp
            )
        }

        documentSnapshots.forEach(doc => {
            var post = doc.data()
            post.docID = doc.id
            this.$store.commit("modules/posts/pushPost", post)
        })
        $state.loaded()
    })
}

This is my infinite loading handler which fetches new DB Entries once the end of the list is reached. Working fine so far.

This is my first fetch when the page gets loaded

async fetch({ store }){
    if (store.state.modules.posts.posts.length < 5) {
        let posts = []
        await db
            .collection("posts")
            .orderBy("timestamp", "desc")
            .limit(3)
            .get()
            .then(querySnapshot => {
                store.commit(
                    "modules/posts/updateLastVisible",
                    querySnapshot.docs[2].data().timestamp
                )
                querySnapshot.forEach(doc => {
                    var x = doc.data()
                    x.docID = doc.id
                    posts.push(x)
                })
            })
        store.commit("modules/posts/fetchedPosts", posts)
    }
}

Basicly the problem is that I get the first 3 entries which I fetch on the page load again when I am fetching in my infinite Loading handler, which leads to the entries being displayed twice, this should not happen because this.lastVisible has the timestamp of the 3rd Element that I fetch on load, so those should be ignored.

After those elements everything is working fine with the .startAfter but the first 3 getting loaded again makes no sense. I checked the store with the devtools and everything is working fine, this.lastVisible has the correct value when the infiniteLoading Handler is called the first time.

Bounty Edit: Okay so I still have the problem I tried to play around with it a bit more to find the issue but its still occuring... I will set a bounty now and I hope anyone is able to help.

like image 698
Badgy Avatar asked Oct 08 '18 17:10

Badgy


1 Answers

You do not actually need the first time fetch. The infiniteHandler will be called on its own when it gets mounted. In case if it does not call then you can try using the function

this.$refs.infiniteLoading.attemptLoad(); // 'infiniteLoading' is the component's ref property

That will actually invoke the infiniteHandler function for you.

EDIT: To check if one of the function is currently running. On the handler part

infiniteHandler($state) {
    //Check if its currently loading
    this.$nextTick(()=>{
       if (this.isDocSnapShotLoading){
           return;
       }
    });

    //set as currently loading
    this.isDocSnapShotLoading = true;

    var next = db
        .collection("posts")
        .orderBy("timestamp", "desc")
        .startAfter(this.lastVisible)
        .limit(3)

    next.get().then(documentSnapshots => {
        //Get the last visible document
        // this.lastVisible =
        // documentSnapshots.docs[documentSnapshots.docs.length - 1]

        if (documentSnapshots.docs.length == 0) $state.complete()
        else {
            this.$store.commit(
                "modules/posts/updateLastVisible",
                documentSnapshots.docs[documentSnapshots.docs.length - 1].data()
                .timestamp
            )
        }

        documentSnapshots.forEach(doc => {
            var post = doc.data()
            post.docID = doc.id
            this.$store.commit("modules/posts/pushPost", post)
        })
        $state.loaded()

        //set completed loading
        this.isDocSnapShotLoading = false;
    })
}

On the fetch part

async fetch({ store }){
    if (store.state.modules.posts.posts.length < 5) {

        //check if currently loading
        this.$nextTick(()=>{
           if (this.isDocSnapShotLoading){
              return;
           }
       });

        //set as currently loading
        this.isDocSnapShotLoading = true;

        let posts = []
        await db
            .collection("posts")
            .orderBy("timestamp", "desc")
            .limit(3)
            .get()
            .then(querySnapshot => {
                store.commit(
                    "modules/posts/updateLastVisible",
                    querySnapshot.docs[2].data().timestamp
                )
                querySnapshot.forEach(doc => {
                    var x = doc.data()
                    x.docID = doc.id
                    posts.push(x)
                })

                //set as completed loading.
                this.isDocSnapShotLoading = false;
            })
        store.commit("modules/posts/fetchedPosts", posts)
    }
}
like image 61
zapping Avatar answered Nov 15 '22 23:11

zapping