Tithira's avatar

Axios get and pagination offset returning duplicate values

I am broadcasting an event trigger upon user creating a post with pusher, and I'm receiving it in a vue template. For easiness I have added infinite loading.

First loading the posts from the DB and i mounted an Echo listener and pushing to the returned posts array.

However when get request trying to offset the results (pagination to only 5 posts) the 6th result is duplicated (2nd page)

This duplication only happens for the 6th result and all the other results are unharmed

When scrolling down without triggering the event, it works fine, it all happens when the event is triggered, and array is unshifted.

Controller

//get request
public function pusherGet(Request $request)
{
   	$jobs = Job::orderBy('created_at','desc')->paginate(5);    	
  	return response()->json($jobs);
}

view component

<template>
    <div>
        <h3 class="text-center">All Jobs</h3><br/>
 
        <div class="container">
            <div class="card" v-for="(job,index) in jobs" :key="index">
                <div class="card-body">
                    <h4 class="card-title">{{ job.id }}</h4>
                    <p class="card-text">{{ job.request_type}}</p>
                </div>
            </div>    
        </div>
        <infinite-loading @infinite="getJob"></infinite-loading>
        
    </div>
</template>
 
<script>
    

     export default {        
        data() {
            return {
               page:1,
               jobs: [],
            }
        },
        mounted() {
            //this.getJob();
            Echo.channel('chat-room.1')
                .listen('JobCreated', (e) => {                   
                    this.jobs.unshift(e.job);                        
            });

        },
        methods: {
            getJob($state){

                axios.get('getjobs', {
                    params: {
                        page: this.page,
                    },
                }).then(({data})=>{
                     
                    if(data.data.length){
                        this.page += 1;
                        this.jobs.push(...data.data)
                        $state.loaded();
                    }else {
                        $state.complete();
                    }                       
                });                     
            }
        },
        created() {        
            
        }
    }
</script>

What is the best approach to avoid this duplication ? Any help would be greatly appreciated

0 likes
3 replies
Tithira's avatar

Thank you so much for the recommendation. The pagination works well with Postman. However I'm unable to make it compatible to infinite scroll. I am getting the posts with GET request, but struggling to initialize it. Would you mind sharing the concept/method you are using ? Thanks

Tithira's avatar

I was able to overcome the cursor issue with this answer on SO , for anyone who wants to refer

Controller.php

//get request
public function pusherGet(Request $request)
{
   	$jobs = Job::orderBy('created_at','desc')->paginate(5);    	
  	return response()->json($jobs);
}

View Component

<template>
    <div>
        <h3 class="text-center">All Jobs</h3><br/>
 
        <div class="container">
            <div class="card" v-for="(job,index) in jobs" :key="index">
                <div class="card-body">
                    <h4 class="card-title">{{ job.id }}</h4>
                    <p class="card-text">{{ job.request_type}}</p>
                </div>
            </div>    
        </div>
        <infinite-loading  @infinite="getJob"></infinite-loading>
        
    </div>
</template>


<script>
export default {
  data() {
    return {
      jobs:[],
      isInitialLoaded: false,
      currentPage: 1,
      lastPage: 0,
    }
  },
  mounted() {
      this.listenNewJobs();
  },
  methods: {

      listenNewJobs() {
        Echo.channel('chat-room.1')
          .listen('JobCreated', (e) => {
              console.log(e);
              this.jobs.unshift(e.job);
        });
      },
      async getJob($state){
      
        await this.fetchData().then((response) => {

          // console.log(response.data);
          this.lastPage = response.data.last_page;

          if (response.data.data.length > 0) {
            response.data.data.forEach((item) => {
              const exists = this.jobs.find((job) => job.id == item.id);
              if (!exists) {
                // this.jobs.unshift(item); // Add to front of array
                this.jobs.push(item);
              }
            });
            if (this.currentPage - 1 === this.lastPage) {
              this.currentPage = 2;
              $state.complete();
            } else {
              this.currentPage += 1;
            }
            $state.loaded();
          } else {
            this.currentPage = 2;
            $state.complete();
          }
        });
        this.isInitialLoaded = true;
      },
      fetchData() {
        const url = this.isInitialLoaded ? `/getjobs?page=${this.currentPage}` : `/getjobs`;
        return axios.get(url);
      },
    }
}

</script>

Please or to participate in this conversation.