[Vuejs]-How to properly initialize Vuex state to avoid additional API calls

3đź‘Ť

I have handled this in various different ways in the past.

If you do not care if the data you are serving might be old, you can simply detect if you already have some items in your array:

const actions = {
    async getRecords({ commit, getters }){
        if (getters.allRecords.length > 0) {
            // Don't bother retrieving them anymore
            return;
        }
        console.log('getting records...');
        const response = await axios.get('/api/records')
        commit('setRecords', response.data)
    },
    async addRecord({ commit }, user) {
        console.log("user :" + JSON.stringify(user))
        const response = await axios.post('/api/records', user)
            .catch(err => console.log(err))
        commit('addRecord', response.data)
    }
}

If you do want to have the updated values in your database, you can consider changing your api to only return changed records after a certain timestamp. For this we need the following:

  • We need to store the timestamp of our last update. The first time we would retrieve everything, and on subsequent requests we would send the timestamp.
  • A way to identify which records to update in the local state, and which records to delete or add. Having something like an id on your records might be helpful.

Let’s assume that instead of returning a flat array of your records, the api returns a response in the format

{
    records: [ ... ],
    removedRecords: [ ... ],
    timestamp: 123456789
}

You would change your state to

const state = {
    records: [],
    recordUpdateTimestamp: null
}

Your action would then look something like this:

async getRecords({ commit, state }){
    const config = {};
    if (state.recordUpdateTimestamp) {
        config.params = {
            timestamp: state.recordUpdateTimestamp
        };
    }

    console.log('getting records...');
    const { data }= await axios.get('/api/records', config)

    commit('setRecords', data.records);
    commit('removeRecords', data.removedRecords);
    commit('setRecordUpdateTimestamp', data.timestamp);
},

I will leave writing the mutations to you.

This would obviously need work in the backend to determine which records to send back, but may have the advantage of cutting down both the amount of returned data and the time processing that data a lot.

👤Sumurai8

1đź‘Ť

FYI you don’t need a shallow getter like the one you have.
Meaning that a getter that doesn’t compute your state has no value might as well use the state itself.

About the practice, it really depends on how important it is to you that “records” has always the freshest data. If you don’t need it to be always fetched, you can have a “initRecords” action to run on your “App.vue” on created hook that you can use to initialize your records. If you need always fresh data, what you have is good enough.

Leave a comment