Search code examples
vue.jsvuexvue-routerstate-management

Vuex is resetting already set states


Have started to play around with Vuex and am a bit confused.

It triggers the action GET_RECRUITERS everytime I load the component company.vue thus also making an api-call.

For example if I open company.vue => navigate to the user/edit.vue with vue-router and them go back it will call the action/api again (The recruiters are saved in the store accordinly to Vue-dev-tools).

Please correct me if I'm wrong - It should not trigger the action/api and thus resetting the state if I go back to the page again, correct? Or have I missunderstood the intent of Vuex?

company.vue

<template>
  <card>

    <select>
      <option v-for="recruiter in recruiters"
              :value="recruiter.id">
        {{ recruiter.name }}
      </option>
    </select>

  </card>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  middleware: 'auth',

  mounted() {
    this.$store.dispatch("company/GET_RECRUITERS")
  },

  computed: mapGetters({
    recruiters: 'company/recruiters'
  }),

}
</script>

company.js

import axios from 'axios'

// state
export const state = {
  recruiters: [],
}

// getters
export const getters = {
  recruiters: state => { 
    return state.recruiters
  }
}

// actions
export const actions = {
  GET_RECRUITERS(context) {

    axios.get("api/recruiters")
      .then((response) => {
        console.log('API Action GET_RECRUITERS')
        context.commit("GET_RECRUITERS", response.data.data) 
      })
      .catch(() => { console.log("Error........") })
  }

}

// mutations
export const mutations = {
  GET_RECRUITERS(state, data) {
    return state.recruiters = data
  }
}

Thanks!


Solution

  • That's expected behavior, because a page component is created/mounted again each time you route back to it unless you cache it. Here are a few design patterns for this:

    • Load the data in App.vue which only runs once.

    • Or, check that the data isn't already loaded before making the API call:

    // Testing that your `recruiters` getter has no length before loading data
    mounted() {
       if(!this.recruiters.length) {
          this.$store.dispatch("company/GET_RECRUITERS");
       }
    }
    
    • Or, cache the page component so it's not recreated each time you route away and back. Do this by using the <keep-alive> component to wrap the <router-view>:
    <keep-alive>
       <router-view :key="$route.fullPath"></router-view>
    </keep-alive>