vuejs / pinia

🍍 Intuitive, type safe, light and flexible Store for Vue using the composition api with DevTools support
https://pinia.vuejs.org
MIT License
13.11k stars 1.05k forks source link

Mutating more than 1 state variables from same action only trigger one mutation #2734

Closed sourcecodeit closed 2 months ago

sourcecodeit commented 2 months ago

Reproduction

https://play.pinia.vuejs.org/#eNqNVF1v2jAU/StWNIkggT3o1EkMKrqtD5v2pXVvTR9CcgG3jm3FTsqE8t93bZOQfqjjARH7nnN87/H13UeXWtO6gmgWzU1Wcm2JAVtpIlK5WSSRNUl0kUheaFVasieVgWurSiANWZeqIAPKMlVJCyW1ZtADlrDuMKiPoURmShrU9/xFJxUP20hR2dRCjjFkxze3ww+O5fH0jalWLsEVxLHHcSVHqIWEIVlckH0iCXEySgAVatOBUJ20yrRORQVUV2bbxSnUIK2h9/AXoQ3+EjlnwQusHBcWCi2QjitCvgelGdnvu3ybxkXmq5Iwj+l/VdYqSZaZ4Nk9+hmKESrNP6c2nWDt0cU3XJHcLecs4E/hTh9zp6dyL4U4MlMherw565UajaJwmeMi1fTOKIk94l1ODgFsDbTB7bg9zSVP3U4SMf9NwRTjVakeDDbHHYJHLXSJDcFyqK1SwoxTzQNta602M8ayXCI+B8HrkkqwTOqCPeMsz+k5nTDBVwwPYlzmsHt8DDLGORSnqLfQ5Vs6eUffe9X67CBaOFUnitfcoC3WYJ+t+eaJKZkqNBdQ/tSurR6bgz6rh69+z5YVdClmW8juX9i/M7uQ9a8S0L4aemXZtNyADeGr6x+ww+8uWKi8Eoh+Jfgb8I1ULscA+1jJHNPu4Xy2X/wdc7n5Y652FqRpi3KJejc83tv86ZXSj+me0bOei8exgRZ2YyOHNZdPRozvJj9AYOdhYVp0o2jRZ8WDVOvBKJzvx8OMxH5CxIeU/EubkZvbQ73+9XTrZuj/0sxXgnX4Kjyw92rb8gixW26ol8Q8bia3YT94c6TgY32BMnWU6QsU/0b/R3h+dtg9yLVX1Ayj5h+EJ+/4

Steps to reproduce the bug

Click button "Load all", it will execute the following action:

loadAll() {
      this.data2 = [2]
      this.data1 = [1]      
    }

But if we subscribe to store mutations we notice that only the first mutation (this.data2 = [2]) triggers the function in the subscription:

store.$subscribe((mutation, state) => {
  console.log(mutation)
  mutated.value.push(mutation.events.key)
})

Expected behavior

I expect the store to trigger a mutation for each mutated state variable:

store.$subscribe((mutation, state) => {
  // this should be executed twice: for data1 and data2 state vaariables
  console.log(mutation)
  mutated.value.push(mutation.events.key)
})

Actual behavior

Currently it only trigger the first mutated state variable.

Additional information

Mutating the second variable in the next tick will work:

loadAll() {
      this.data2 = [2]
      nextTick(() => {
         // now the second mutation is triggered
         this.data1 = [1]      
      })
    }
posva commented 2 months ago

This is intended, it's inherent to watch behavior when changing multiple properties in one object (here, $state). You can either directly watch each property individually or use flush: 'sync':

store.$subscribe((mutation, state) => {
  console.log(mutation)
  mutated.value.push(mutation.events.key)
}, { flush: 'sync' })