Search code examples
vue.jsvuex

How to get vuex pagination to be reactive?


I am not sure what the problem is. I am creating a Vue/Vuex pagination system that calls my api to get my list of projects. The page initially loads all the projects in when the page is mounted. The Vuex does the inital call with axios. Vuex finds the projects and the number of pages. Once the user clicks on the pagination that is created with the pagination component, it should automatically change the projects for page 2...3 etc.

The problem I have is that it is not reactive until you press the page number twice. I am using vue 3. I have tried not using Vuex and that was successful. I am trying to create a single store that does all the axios calls. Thanks for all your help!

Vuex store

import { createStore } from 'vuex';
import axios from 'axios';

/**
 * Vuex Store
 */

export const store = createStore({
    state() {
        return {
            projects: [],
            pagination: {}
        }
    },
    getters: {
        projects: state => {
            return state.projects;
        }
    },
    actions: {
        async getProjects({ commit }, page = 1) {
            await axios.get("http://127.0.0.1:8000/api/guest/projects?page=" + page)
                .then(response => {
                    commit('SET_PROJECTS', response.data.data.data);
                    commit('SET_PAGINATION', {
                        current_page: response.data.data.pagination.current_page,
                        first_page_url: response.data.data.pagination.first_page_url,
                        prev_page_url: response.data.data.pagination.prev_page_url,
                        next_page_url: response.data.data.pagination.next_page_url,
                        last_page_url: response.data.data.pagination.last_page_url,
                        last_page: response.data.data.pagination.last_page,
                        per_page: response.data.data.pagination.per_page,
                        total: response.data.data.pagination.total,
                        path: response.data.data.pagination.path
                    });
                })
                .catch((e) => {
                    console.log(e);
                });
        }
    },
    mutations: {
        SET_PROJECTS(state, projects) {
            state.projects = projects;
        },
        SET_PAGINATION(state, pagination) {
            state.pagination = pagination;
        }
    },
});

Portfolio Component

<template>
  <div>
    <div id="portfolio">
      <div class="container-fluid mt-5">
        <ProjectNav></ProjectNav>
        <div class="d-flex flex-wrap overflow-auto justify-content-center mt-5">
          <div v-for="project in projects" :key="project.id" class="m-2">
            <Project :project="project"></Project>
          </div>
        </div>
      </div>
    </div>
    <PaginationComponent
      :totalPages="totalPages"
      @clicked="fetchData"
    ></PaginationComponent>
  </div>
</template>

<script>
import Project from "../projects/Project.vue";
import PaginationComponent from "../pagination/PaginationComponent.vue";
import ProjectNav from "../projectNav/ProjectNav.vue";

/**
 * PortfolioComponent is where all the projects are displayed.
 */
export default {
  name: "PortfolioComponent",
  data() {
    return {
      location: "portfolio",
      projects: []
    };
  },
  components: {
    Project,
    PaginationComponent,
    ProjectNav,
  },
  mounted() {
    this.fetchData(1);
  },
  computed: {
    totalPages() {
      return this.$store.state.pagination.last_page;
    },
  },
  methods: {
    fetchData(page) {
      this.$store.dispatch("getProjects", page);
      this.projects = this.$store.getters.projects;
    },
  },
};
</script>

Solution

  • In your fetchData method you are calling the async action getProjects, but you are not waiting until the returned promise is resolved.

    Try to use async and await in your fetchData method.

      methods: {
        async fetchData(page) {
          await this.$store.dispatch("getProjects", page);
          this.projects = this.$store.getters.projects;
        },
      },