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
booksis an object obtained through av-forand 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.
EDIT: More code
I decided to edit the question to show how books are generated and populated.
<template>
<figure v-for="(book, index) in books" :key="index">
<Button text="+" @click="addBook(book)" />
<!-- I omitted the use of the other elements to make things more objective. -->
</figure>
</template>
<script>
export default {
data() {
return {
books: {},
};
},
methods: {
search() {
axios
.get(`https://www.googleapis.com/books/v1/volumes?q=${this.seek}`)
.then((response) => {
this.books = response.data.items.map((item) => ({
id: item.id,
title: item.volumeInfo.title,
authors: item.volumeInfo.authors || [this.$t("book.unknown-author")],
ISBN: item.volumeInfo.industryIdentifiers?.[0].identifier ?? item.id,
thumbnail: item.volumeInfo.imageLinks?.thumbnail ?? this.noCover,
}));
})
.catch((error) => console.error(error))
},
addBook(book) {
// Object.assign({}, book)
book = { ...book };
this.$store.dispatch("addBook", book);
},
},
};
</script>
book = Object.assign({}, book)can fix "state.userBooks.push is not a function" error. Consider providing a way to reproduce it.} mutations- this is syntax error, this suggests that the code differs in some waybooksare generated and populated.books: {}-this. If it's expected to be an array, it should be an array. But I see no direct connection with the error you have. If the problem persists, consider providing a demo that can reproduce it. I'd expect to seeuserBooks = someObjectin some part of the store, otherwise it cannot be nothing but an array and so it should havepushmethod. You can also debug and check what exactly userBooks is when the error occurs