TJ Weems
TJ Weems

Reputation: 1114

How To Mutate Array Of Objects In Vue

I am trying to mutate my array after updating objects with the new values. Currently when I use splice() it has been for only mutating single object. Perhaps I am looking for simple javascript method but I am trying to figure out how mutate array if I am updating multiple objects simultaneously?

This is the store action I am using to commit response.data

updateCheckedEngagements(context, checkedEnagements) {  
      axios.patch('/engagementsarray', {
        engagements: checkedEnagements.engagements,
        assigned_to: checkedEnagements.assigned_to,
        status: checkedEnagements.status
      })
      .then(response => {
          console.log(response.data)
          context.commit('updateCheckedEngagements', response.data)
      })
      .catch(error => {
          console.log(error.response.data)
      })           
    },

here is the mutation I have currently set up but I do not think it is correct

    updateCheckedEngagements(state, engagement) {
          const index = state.engagements.findIndex(item => item.id == engagement.id);
          state.engagements.splice(index, 1, {
            'id': engagement.id,
            'assigned_to': engagement.assigned_to,
            'status': engagement.status,
          })
        },

Also since I am passing checkedEngagements as my parameter in the store action, does that also have to be the 2nd parameter for the mutation?

Upvotes: 0

Views: 2357

Answers (1)

aBiscuit
aBiscuit

Reputation: 4732

If you expect to update multiple objects simultaneously, value argument provided in mutation (engagement in code above), should be an array.

We can return new state of engagements with updated values with following code, as an example:

const actions = {
  updateCheckedEngagements(state, updatedEngagements = []) {
    // Create list of ids, to simplify index matching
    const ids = updatedEngagements.map(engagement => engagement.id)
    state.engagements = state.engagements.map(engagement => {
      // Check if updated engagement matches currently iterated one
      const matchedIndex = ids.indexOf(engagement.id)
      // If index matches, we shall replace current item with updated values
      if (matchedIndex !== -1) {
        return {
          ...updatedEngagements[matchedIndex]
        }
      }
      // Return previous value by default
      return engagement
    })
  }
}

It is a good practice to avoid using array mutating methods inside mutations to ensure that state watchers will be notified and reactivity works as expected: all state values are updated and getters recomputed.

Upvotes: 2

Related Questions