'How to fetch data from API in vuex

I want to use vuex to store some data fetched from the server that my SPA Vue app will need in different pages, this to avoid that a new ajax request is made every time that the user will change product page (it's an headless ecommerce).

My question is simple, how I can push the fetched data into an array that is defined in my store? How I will get the data in my components? I'm writing the code but not sure if I've done it well.

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

export default createStore({
  state: {
    products: []
  },
  mutations: {
    updateProductsData(state, products){
      // not sure how to proceed here
    }
  },
  actions: {
    fetchProducts(){
      const baseURL = 'https://www.example.com/app/index.php/wp-json/shop/v1/products';
      let productsData = [];
      axios.get(baseURL).then( response => {
        response.data.forEach( el => {    
          console.log(el);
          let details = {
            id: el.id,
            slug: el.slug,
            name: el.name,
            price: el.price,
            description: el.description,
            short_description: el.short_description
          }
          productsData.push(details);
        });
        store.commit('updateProductsData', productsData);
      }).catch( e => console.log(e) );
    }
  }
})

In my components where I need to load the data I have this code


export default {
  name: 'Home',
  data(){
    return {
      loaded: false,
      offers: [],      
    }
  },
  created(){

  }, 
  mounted(){
    this.$store.dispatch('fetchProducts').then( res => this.offers.push(res) )   
  },
}


Solution 1:[1]

Inside your updateProductsData mutation use state.products = [...products] to add your loaded products to your state

Check https://www.vuemastery.com/courses/vuex-fundamentals/vuex4-intro-to-vuex for a short intro to Vuex

Solution 2:[2]

You can refer to the doc of Vuex about the use of actions and mutations https://vuex.vuejs.org/guide/actions.html . It's detailed...

As Vuex suggests, you should put async operations in actions (like fetching data from the server in your example). Then you should commit a "mutation" to use the fetched data to set your state like the code given below

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

export default createStore({
  state: {
    products: []
  },
  mutations: {
    updateProductsData(state, products){
      // here set your state
      state.products = products
    }
  },
  actions: {
    fetchProducts({commit}){
      const baseURL = 'https://www.example.com/app/index.php/wp-json/shop/v1/products';
      let productsData = [];
      axios.get(baseURL).then( response => {
        response.data.forEach( el => {    
          console.log(el);
          let details = {
            id: el.id,
            slug: el.slug,
            name: el.name,
            price: el.price,
            description: el.description,
            short_description: el.short_description
          }
          productsData.push(details);
        });
        store.commit('updateProductsData', productsData);
      }).catch( e => console.log(e) );
    }
  }
})

If you want to use the state in your components, you can put it in computed attribute.

export default {
  name: 'Home',
  data(){
    return {
      loaded: false,
    }
  },
  computed:{
    // map this.offers to store.state.products
    offers(){
      return this.$store.state.products
    }
  },
  created(){

  }, 
  mounted(){
    // dispatch 'fetchProducts' to fetch data
    this.$store.dispatch('fetchProducts')
  },
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 andreasbecker.de
Solution 2