Teoman Kirac
Teoman Kirac

Reputation: 778

vue.set() an array in a vuex mutation

I am trying to vue.set() an array in a "updateInformation" mutation in my vuex store.

Here is my function in my script:

 updateImagesArrayInMutation(imageFile) {
      let images = [];
      this.images.forEach(imageFile => {
        imageFile.generateBlob(
          blob => {
            let rand = (Math.random().toString(36).substring(2, 16) + Math.random().toString(36).substring(2, 16)).toUpperCase()
            let imagesRef = firestorage.ref('postimages/' + rand)
            console.log("imageRef, imageFile for eachfile", imageFile)
            if(this.images.length < 3) {
              // THIS PUSHES AN EMPTY CROPPA ("CLICK DRAGE IMAGE HERE") // max 5
              this.images.push({})
              console.log("imagesRef", imagesRef.fullPath)
            }
            this.updateImages ({ 
              images: imagesRef.fullPath
            })
          },
          'image/jpeg',
          0.8,
        )
      })
    },
    updateImages(images) {
      console.log("this is value from closure", images)
      this.updateInformation({
        images: images,
        title: this.post.title,
        description: this.post.description
      })
    },

This is the mutation in my store:

  [UPDATE_INFORMATION] (state, info) {
    console.log('[STORE MUTATIONS] - UPDATE_INFORMATION:', info)

    Vue.set(state.newPost.images, 'images', [...info.images])

    // state.newPost.images = info.images
    state.newPost.title = info.title
    state.newPost.description = info.description
    state.newPost.location = info.location
    state.newPost.city = info.city
  },

Can I do this? Thank you in advance for any suggestions.

Upvotes: 0

Views: 2660

Answers (3)

Jason Smith
Jason Smith

Reputation: 1209

You do not need to use Vue.set(). The purpose of Vue.set() is to add new properties to an object, not to change existing properties.

In your Vuex initial state, it would make most sense to me to initialize this way:

newPost: { images: [], title: '', description: '', location: '', city: '' }

Now your images property is an array, as expected, rather than a string.

In the UPDATE_INFORMATION mutation, you can do either:

state.newPost.images = info.images

Or:

state.newPost.images = [...info.images]

If you want a shallow copy of the info.images array instead of referring to it directly.

Upvotes: -1

skirtle
skirtle

Reputation: 29092

I don't know some of the libraries you're using but I think I understand what you're trying to do. In short, you're trying to replace multiple calls to mutate the store state with a single call that passes an array of image paths.

Switch the first few lines to use Promises, like this:

const imagePromises = this.images.map(imageFile => {
  return imageFile.promisedBlob('image/jpeg', 0.8).then(blob => {

Then inside the then callback return the relevant image path rather than calling updateImages:

return imagesRef.fullPath

This will give you an array of Promises that resolve to the paths you want. You can then use Promise.all to wait for all the Promises:

Promise.all(imagePromises).then(imagePaths => {
  // imagePaths should be an array of strings
  this.updateImages(imagePaths)
})

That should get you the array of path strings that you want.

Upvotes: 1

T. Short
T. Short

Reputation: 3614

Why not just do it like this:

[UPDATE_INFORMATION] (state, info, payload) {
    state.newPost = {
        ...state.newPost,
        ...info
    }
}

Upvotes: 2

Related Questions