Search code examples
javascriptvue.jsaxiosvuex

Error in v-on handler: "TypeError: Cannot read property 'emailAddress' of undefined" VUEX


I'm having trouble figuring this out with the vuex store. I have a created a subscription form to be able to enter your email address and I want to make a post request to the backend api but the data is not showing when I console.log it. It only console.logs the item that has been dispatch to the store and when I'm trying to mutate the item to the state.emailAddress and try to get the data that to the POST I get an empty object. enter image description here

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

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    pizzaItems: [],
    shopCart: [],
    choosePizzaSize: [],
    total: 0,
    deliveryCharge: 0,
    emailAddress: '',
  },
  getters: {
    deliveryCharge: state => state.deliveryCharge,
    pizzaItems: state => state.pizzaItems,
    shopCart: state => state.shopCart,
    choosePizzaSize: state => state.choosePizzaSize,
    checkOut: state => state.total,
  },
  mutations: {
    Add_To_Cart(state, item) {
      const shopItem = state.shopCart.find(x => x.id === item.id && x.size === item.size);
      if (shopItem) {
        shopItem.count += item.count;
      } else {
        state.shopCart.push(item);
      }
    },
    Price_Total(state, total) {
      state.total = total;
    },
    fetchProducts(state, products) {
      state.pizzaItems = products;
    },
    fetchPizzasize(state, size) {
      state.choosePizzaSize = size;
    },
    free_Shipping(state, freeshipping) {
      state.deliveryCharge = freeshipping;
    },
    subScribeMail(state, item) {
      state.emailAddress = item;
    },
  },
  actions: {
    fetchData({ commit }) {
      axios.get('http://localhost:3000/saltbageproducts').then((response) => {
        commit('fetchProducts', response.data.products);
        commit('fetchPizzasize', response.data.pizzasize[0].pizzaSize);
      })
        .catch((err) => {
          console.log(err);
        });
    },
    addTocart(context, item) {
      context.commit('Add_To_Cart', item);
    },
    priceCalculation(context, item) {
      context.commit('Price_Total', item);
    },
    changeFreeshippingStatus(context, shipping) {
      context.commit('free_Shipping', shipping);
    },
    emailCheckUp(context, item, state) {
      context.commit('subScribeMail', item);
      axios.post('http://localhost:3000/saltbagehome', {
        email: state.emailAddress,
      }).then((reponse) => {
        console.log(reponse.data);
      }).catch((err) => {
        console.log(err);
      });
    },
  },
  modules: {
  },
});


Solution

  • Acoording Vuex documentation;

    Register actions on the store. The handler function receives a context object that exposes the following properties:

    {
      state,      // same as `store.state`, or local state if in modules
      rootState,  // same as `store.state`, only in modules
      commit,     // same as `store.commit`
      dispatch,   // same as `store.dispatch`
      getters,    // same as `store.getters`, or local getters if in modules
      rootGetters // same as `store.getters`, only in modules
    } 
    

    And also receives a second payload argument if there is one.

    Then in your first parameter of your action u have the vuex context, there should be:

    emailCheckUp(context, item) { ... }
    

    instead of

    emailCheckUp(context, item, state) { ... }
    

    now to access to vuex context inside of your action, just:

    emailCheckUp(context, item) {
      context.commit('subScribeMail', item);
      ...
      email: context.state.emailAddress,
      ...
    }
    

    In practice, they often use ES2015 argument destructuring to simplify the code a bit:

    emailCheckUp({commit, state}, item) {
      commit('subScribeMail', item);
      ...
      email: state.emailAddress,
      ...
    }