'Firestore with getDownloadURL in vuex store
I'm having real difficulties with combining onSnapshot with getDownloadURL in my actions and setting it on mutations to change my state in vuex. I keep getting "[vuex] do not mutate vuex store state outside mutation handlers" error.
Here is a sample of my code:
state = () => ({
products:[]
})
mutations = {
setProducts(state, products) {
state.products = products
console.log(state.products)
},
}
actions = {
setProducts({commit}) {
let colRef = collection(db, 'products')
const unsub = onSnapshot(colRef, snapshot => {
let products = []
snapshot.docs.forEach(doc => {
const imageDownloadURL = getDownloadURL(ref(storage, `${doc.data().imageRef}`))
.then( url => {
// console.log(url)
products.push({
id: doc.id,
name: doc.data().name,
price: doc.data().price,
description: doc.data().description,
imageURL: url
})
commit('setProducts', products)
})
})
})
},
}
I've got a collection that looks like the following:
{
id: 1,
name: 'NotPot Orange',
price: '8.80',
description: 'This is an orange flavour vitamin',
imageURL: 'images/notpot1.jpg'
},
My console.log gives the data I want in this output:
{
id: 'qv1t4f2NfAo9N4YrkXzg',
name: 'NotPot Citrus',
price: '6.50',
description: 'This is a citrus flavour vitamin',
imageURL: 'https://firebasestorage.googleapis.com/v0/b/blahblahblah-
project.appspot.com/o/images%2Fnotpot5.jpg?alt=media&token=385a5a25-ef2c'
},
I've got a getter which I grab in my v-for:
getters = {
products: (state) => {
return state.products
},
}
like so:
<feature-product
v-for="product in this.$store.getters.products"
:key="product.id"
:product="product"
/>
Am I missing smth? I'm really not so versed with onSnapshot and getDownloadURL - so I feel like it's a mistake somewhere there. I heard smth about needing to deepClone/deepCopy but not sure what that means. Any clue or point to the right direction will help out loads! Thanks in advance!
Solution 1:[1]
I'm still not 100% sure if this is the correct method - but I got it to work with {getDocs} from 'firebase/firestore' along side {ref, getDownloadURL} from 'firebase/storage'
I decided to drop the aforementioned real-time data pull to just getDocs in one go - so its not exactly how I wanted it but I thought it's still applicable to my use case. Here's my changes:
actions = {
async setProducts({commit}) {
let colRef = collection(db, 'products')
const querySnapshot = await getDocs(colRef)
querySnapshot.forEach((doc) => {
let products
const imageDownloadURL = getDownloadURL(ref(storage, `${doc.data().imageRef}`))
.then( url => {
// console.log(url)
products = ({
id: doc.id,
name: doc.data().name,
price: doc.data().price,
description: doc.data().description,
imageURL: url
})
commit('setProducts', products)
})
})
}
}
changes to my mutations:
mutations = {
setProducts(state, products) {
state.products.push(products)
console.log(state.products)
},
}
P.S. to get it to be load at the earliest possible point - you can use beforeCreated() or created() lifecycle hooks to dispatch the 'setProducts' action.
Hope this helps for anyone else stuck on smth similar.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | shoski |
