vuejs / pinia

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

Basic counter changed in getter not updated after upgrading to vue 3.4.29 #2700

Closed leifcr closed 1 month ago

leifcr commented 1 month ago

Reproduction

Create a basic vue app with a simple store, then call useIdStore().nextId multiple times. it's expected to return incremented ids/counter.

Steps to reproduce the bug

Here is the basic store:

import { defineStore } from 'pinia';

export const useIdStore = defineStore('idStore', {
  state: () => ({
    nextElementIdCounter: 0,
  }),
  getters: {
    // Example getter
    nextId: (state) => {
      state.nextElementIdCounter += 1;
      return state.nextElementIdCounter;
    },
  },
  actions: {
    // Example action
    incrementCounter() {
      this.nextElementIdCounter++;
    },
  },
});

When calling useIdStore().nextId, it's expected to increment for each call. This works as expected in Vue 3.4.27, but is broken in vue 3.4.29

See this example with Vue 3.4.27, that works fine: https://stackblitz.com/edit/vitejs-vite-h2rymf?file=src%2FApp.vue Example with Vue 3.4.29 that is broken: https://stackblitz.com/edit/vitejs-vite-nctroe?file=src%2FApp.vue

Expected behavior

I expected the counter to still increment

Actual behavior

The counter does not increment

Additional information

I know it's not best practice to change the state in a getter, but I found the use case when requesting a new id or next id, better to change the state in a getter, rather than calling the action, then the getter in sequence.

leifcr commented 1 month ago

Works fin in Vue 3.4.28 as well: https://stackblitz.com/edit/vitejs-vite-swtzu1?file=src%2Fstores%2FidStore.ts

posva commented 1 month ago

Having a getter like that is equivalent to writing this:

computed(() => {
      nextElementIdCounter.value++
      return nextElementIdCounter.value
})

As you can imagine this simply doesn't make sense as it creates a recursive dep. Fortunately, Vue doesn't seem to crash but such definition is not valid in Vue.