Home > Net >  How to push to an array via a Mutation in Vuex?
How to push to an array via a Mutation in Vuex?

Time:12-27

At the time I was writing this question I found the solution to my problem, but even so I decided to share it with the community to see if I'm solving the problem in the best way possible.

Given a summary of my Store:

//  store/index.js

const store = createStore({
  state: {
    userBooks: [],
  }
  mutations: {
    setUserBooks(state, val) {
      state.userBooks.push(val);
    },
  actions: {
    addBook({ commit }, payload) {
      commit("setUserBooks", payload);
  }
})

I'm calling the action like this:

//  Add.vue

methods: {
  addBook(book) {
    this.$store.dispatch("addBook", book);
  },
}

This was giving me the following error:

Uncaught (in promise) TypeError: state.userBooks.push is not a function
  • books is an object obtained through a v-for and contains properties like id, title, author, thumbnail, and ISBN.

I had already checked this solution: Push to vuex store array not working in VueJS. And that's exactly what I tried, but I got the above error.

How I solved the problem:

I noticed that the book object was coming into the function as a proxy object. With that in mind, I turned the proxy object into a regular object as follows:

addBook(book) {
  book = Object.assign({}, book);
  this.$store.dispatch("addBook", book);
}

Why does the problem happen?

I confess that I still don't understand why the problem occurs. book is obtained via the v-for of books. books is assembled from a Google Books API query. The query is done using axios.get().then()

The console.log(this.books) already returns me a proxy object and I confess that I don't know if this is the expected behavior and if I should try to change it.

Anyway the problem is solved, but if anyone has any different approach I would be very happy to learn something new.

CodePudding user response:

Another new faster way is spread operator.

book = { ...book }

And you can use it in arrays to if val is an array with and object if not just don't type ... before val.

setUserBooks(state, val) {
      state.userBooks = [...state.userBooks, ...val];
}

Or for example you have big object called user and you have in this object his address object and he wants to change it.

setUser(state, address) {
      state.user = {...state.user, address};
}

CodePudding user response:

The first parameter is not a state but context object. This can be deduced from the fact that there would be no access to commit if it were a state.

It should be:

setUserBooks({ state }, val) { ...
  • Related