prazdevs / pinia-plugin-persistedstate

💾 Configurable persistence and rehydration of Pinia stores.
https://prazdevs.github.io/pinia-plugin-persistedstate/
MIT License
2.05k stars 118 forks source link

[core] Persisted state doesn't update when calling this.$reset() and then setting state values #52

Open christianlmc opened 2 years ago

christianlmc commented 2 years ago

Minimal example:

export const useStore = defineStore('main', {
  state: () => ({
    counter: 0,
  }),
  persist: true,
  actions: {
    // If this function is not async with await on $reset, the localstorage doesn't update (even though pinia does update)
    // If F5 is pressed after setCounter has been called, counter will go back to previous state instead of 100
    setCounter100() {
      this.$reset();
      this.counter = 100
    },
  },
})
prazdevs commented 2 years ago

Hi, what versions are you running ? I tried with the examples given in the repo (using vite + vue3) and with your exact store it works fine and properly saves counter as 100 in the storage, and rehydrates properly.

If you could provide a complete repo with your problem so it can be investigated. thanks :)

christianlmc commented 2 years ago

Sorry it took me so long, here is an example repo of the issue

https://github.com/christianlmc/bug-pinia-plugin-persistedstate

prazdevs commented 2 years ago

Okay, i investigated a bit, and there seems to be some off behaviour with the $reset method. The way mutations are committed is not the same on the very first time, and the following ones. If you put this in your HomeView.vue

<script setup lang="ts">
import { useCounterStore } from "@/stores/counter";
import { storeToRefs } from "pinia";

const counterStore = useCounterStore();
const { counter } = storeToRefs(counterStore);
const { setCounter100 } = counterStore;

counterStore.$subscribe((e) => { console.log(e) })

</script>

<template>
  <main>
    <button @click="setCounter100">do thing</button>
    <div style="font-size: 3rem">Counter</div>
    {{ counter }}
    <input v-model="counter" />
    <div>Look at Local Storage, on the 'Application' tab on the Inspector</div>
    <div>It shows {"counter":0} (Tested on Chrome 99)</div>
  </main>
</template>

After loading the page, the first click on the button will give you 2 subscription events, and the state will be store in localStorage properly, but if you click again, only 1 subscription event containing everything is emitted, and the state is not persisted correctly. Reloading the page resets this behaviour every time. This seems more like a pinia issue/behaviour im not aware of.

Also it seems suspiciously tied to this issue https://github.com/vuejs/pinia/issues/1129

prazdevs commented 2 years ago

or this one https://github.com/vuejs/pinia/issues/992

christianlmc commented 2 years ago

Thank you @prazdevs, I will keep using the await this.$reset workaround for the time being

ThatDeveloper commented 1 year ago

Hey there @prazdevs Is there an update on this matter? I can not make it work, even with the await. Could you maybe provide an example?

MalronWall commented 2 months ago

Hey @prazdevs ! 🖐 I have the same problem here... Do you have any advice ? I tried this :

async resetData(): Promise<void> {
  sessionStorage.removeItem('@actualStore')
  this.$reset()
  await this.save() // save in db
}

It works properly without the persist: true but not with... 😅 And the await this.$reset() described previously does not work too... Thank you ! 🙏