1

I have a vuejs component and a vuex store.

I would like to send data from vue component to vuejs store and then call a function in vuex that's push data to a db.

I get the data from currentUser (that works), but in vuex store I get the error: Cannot read property 'push' of null.

I run createPost that works but the data does not pushed to vuex store I think because the error above.

#vuejs component
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
import {
  SET_NEWPOST,
  ADD_TAGS,
  SET_USERDATA,
  SET_GENERAL
} from "@/store/posts/mutations";

methods: {
  ...mapMutations("posts", {
    updateInformation: SET_NEWPOST,
    setUserData: SET_USERDATA,
    addGeneral: SET_GENERAL,
    addTags: ADD_TAGS
  }),

  ...mapActions("posts", {
    create: "triggerAddProductAction"
  }),

  async createPost() {
      this.updateInformation({
        content: this.content,
        url: this.newOne
      });
      this.updateUserData();

      this.createOne();

  }
}

vuex store

...
const state = {
  products: []
}    

const mutations = {
   [addProduct]: (state, product) => state.products.push(product)
},

const actions: {
  createUserProduct: async ({ commit, rootState }, product) => {
    const userProductDb = new UserProductsDB(
        rootState.authentication.user.id
    );

    const createdProduct = await userProductDb.create(product);
    commit("addProduct", createdProduct);
 },
 triggerAddProductAction: ({ dispatch, state, commit }) => {
    const post = state.newPost;
    dispatch("createUserProduct", post);
 }
}
5
  • 1
    You pass the data as the second parameter to dispatch, for example to pass a value of 1 use: this.$store.dispatch('createUserProduct', 1) Commented May 1, 2019 at 15:53
  • yeah I understand, but does not helped me Commented May 1, 2019 at 15:57
  • const post = .. is empty and I don't know why Commented May 1, 2019 at 15:58
  • I think it is because of the way you formatted the object Commented May 1, 2019 at 15:58
  • I tested different ways but each time the same error Commented May 1, 2019 at 15:59

2 Answers 2

3

Your format I believe is a little off. Try building the store like this. Remember that using arrow functions vs non-arrow functions can also have a side effect in what is being referenced.

Mostly what can be seen, is that I removed the const's, and placed it all in the object literal directly. I also remove the Destructuring of addProduct as it doesn't seem logical here.

const store = new Vuex.Store({
  state: {
    products: []
  },
  mutations: {
    addProduct: (state, product) => {
      state.products.push(product)
      console.log('Added Product:', product)
      console.log('products', state.products)
    }
  },
  actions: {
    async createUserProduct({ commit }, product) {
      commit("addProduct", product);
    }
  }
});

new Vue({
  el: "#app",
  store,
  mounted() {
    this.$store.dispatch('createUserProduct', 1)
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.0/vuex.min.js"></script>
<div id="app"></div>

Sign up to request clarification or add additional context in comments.

6 Comments

Are you sure that it is referencing this push? Do you have a push somewhere else?
it is the only one I have in vuex
I have updated the answer, and the code works, as you can see if you run it. There must be something else that you are doing that is setting the value of products to null.
yeahh I think too. Your example explain it in a good way, I changed my code but same error again :/
Is it possible that UserProductsDB or userProductDb.create() is manipulating the value somehow?
|
1

I think one of the main problems here is actually that you call mutations directly in your component. Mutations should always be called by actions and not directly. This is because mutations are synchronous and actions can be asynchronous. From Vuex docs:

On to Actions Asynchronicity combined with state mutation can make your program very hard to reason about. For example, when you call two methods both with async callbacks that mutate the state, how do you know when they are called and which callback was called first? This is exactly why we want to separate the two concepts. In Vuex, mutations are synchronous transactions:

store.commit('increment')
// any state change that the "increment" mutation may cause
// should be done at this moment.

To handle asynchronous operations, let's introduce Actions.

That's why you should have a structure like this:

export const mutations = {
  ADD_EVENT(state, event) {
    state.events.push(event)
  },
  SET_EVENTS(state, events) {
    state.events = events
  },
  SET_EVENTS_TOTAL(state, eventsTotal) {
    state.eventsTotal = eventsTotal
  },
  SET_EVENT(state, event) {
    state.event = event
  }
}
export const actions = {
  createEvent({ commit, dispatch }, event) {
    return EventService.postEvent(event)
      .then(() => {
        commit('ADD_EVENT', event)
        commit('SET_EVENT', event)
        const notification = {
          type: 'success',
          message: 'Your event has been created!'
        }
        dispatch('notification/add', notification, { root: true })
      })
      .catch(error => {
        const notification = {
          type: 'error',
          message: 'There was a problem creating your event: ' + error.message
        }
        dispatch('notification/add', notification, { root: true })
        throw error
      })
  }

Check also this video out by vuemastery even featured on the official vuex docs: https://www.vuemastery.com/courses/mastering-vuex/intro-to-vuex/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.