How to call an action (NuxtJs)

Viewed 4155

I'm trying to call an action in my vue from my store.

This is my file aliments.js in my store:

import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios';

Vue.use(Vuex, axios);

export const state = () => ({
  aliments: {},
})
export const mutations = () => ({
  SET_ALIMENTS(state, aliments) {
    state.aliments = aliments
  }
})
export const actions = () => ({
  async getListAliments(commit) {
    await Vue.axios.get(`http://localhost:3080/aliments`).then((response) => {
      console.log(response);
      commit('SET_ALIMENTS', response);
    }).catch(error => {
      throw new Error(`${error}`);
    })
    // const data = await this.$axios.get(`http://localhost:3080/aliments`)
    // commit('setUser', user)
    // state.user = data;
    // return state.user;
  }

})
export const getters = () => ({
  aliments (state) {
    return state.aliments
  }
})

I want to diplay a list of aliments in my vue with :

{{ this.$store.state.aliments }}

I call my action like this :

<script>
import { mapGetters, mapActions } from 'vuex'

export default {

  computed: {
    ...mapGetters(['loggedInUser', 'aliments']),
    ...mapActions(['getListAliments']),
    getListAliments() {
      return this.$state.aliments
    }
  }
}
</script>

I don't understand where is my mistake :/

NB: I also tried with a onclick method on a button with a dispatch('aliments/getListAliments')... but doesn't work...

2 Answers

The problem is that you're mapping your actions in the "computed" section of the component, you should map it in the "methods" section !

Hi and Welcome to StackOverflow

to quickly answer to your question, you would call an action as:

this.$store.dispatch('<NAME_OF_ACTION>', payload)

or though a mapActions as

...mapActions(['getListAliments']), // and you call `this.getListAliments(payload)`

or yet

...mapActions({
  the_name_you_prefer: 'getListAliments' // and you call `this.the_name_you_prefer(payload)`
}), 

for getters, it's the same process, as you already have 2 definitions ['loggedInUser', 'aliments'] you simply call the getter like if it was a computed value <pre>{{ aliments }}</pre>

or when we need to do a bit more (like filtering)

getListAliments() {
    return this.$store.getters['aliments']
}

But I can see your store is as we call, one-to-rule-them-all, and because you are using Nuxt, you can actually leverage the module store very easy

as your application grows, you will start store everything in just one store file (the ~/store/index.js file), but you can easily have different stores and instead of what you wrote in index.js it can be easier if you had a file called, taken your example

~/store/food.js with

import axios from 'axios'

export const state = () => ({
    aliments: {},
})

export const getters = {
    aliments (state) {
        return state.aliments
    }
}

export const mutations = {
    SET_ALIMENTS(state, aliments) {
        state.aliments = aliments
    }
}

export const actions = {
    async getListAliments(commit) {
        await axios.get('http://localhost:3080/aliments')
            .then((response) => {
                console.log(response);
                commit('SET_ALIMENTS', response.data);
            }).catch(error => {
                throw new Error(`${error}`);
            })
  }
}

BTW, remember that, if you're using Nuxt serverMiddleware, this line

axios.get('http://localhost:3080/aliments')...

would simply be

axios.get('/aliments')...

and to call this store, all you need is to prefix with the filename, like:

...mapActions(['food/getListAliments'])
// or
...mapActions({ getListAliments: 'food/getListAliments' })
// or
this.$store.commit('food/getListAliments', payload)

another naming that could help you along the way:

  • on your action getListAliments you're actually fetching data from the server, I would change the name to fetchAliments

  • on your getter aliments you're actually returning the list, I would name it getAllAliments

have fun, Nuxt is amazing and you have a great community on Discord as well for the small things :o)


EDIT

also remember that actions are set in methods

so you can do:

...
export default {
    methods: {
        ...mapActions(['getListAliments]),
    },
    created() {
        this.getListAliments()
    }
}

and in your Store action, please make sure you write

async getListAliments({ commit }) { ... }

with curly braces as that's a deconstruction of the property passed

async getListAliments(context) { 
   ...
   context.commit(...)
}
Related