Reputation: 1217
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.
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);
}
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.
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>
Upvotes: 2
Views: 1718
Reputation: 4623
Another new faster way is spread operator. You create a new object and spred variables inside book object. It works same as book = Object.assign({}, book)
book = { ...book }
Bellow more examples of usage of spred operator:
val
is an array with and object if not just don't type ...
before val
.setUserBooks(state, val) {
state.userBooks = [...state.userBooks, ...val];
}
user
and you have in this object his address
object and he wants to change it.setUser(state, address) {
state.user = {...state.user, address};
}
Upvotes: 1