prazdevs / pinia-plugin-persistedstate

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

It cannot work when create store before pinia #352

Open seepine opened 4 weeks ago

seepine commented 4 weeks ago

Are you using Nuxt?

Describe the bug

axios.js

// it cannot work
const userStore = useUserStore(pinia);

axios.interceptors.request.use(
  (request) => {
    // in here, it can work
    // const userStore = useUserStore(pinia);
    if (userStore.user) {
      console.log('axios request: ', userStore.user);
    }
    return request;
  },
  (error) => Promise.reject(error)
);

main.js

import { pinia } from './stores';
import { axios } from './axios';

window.axios = axios;
createApp(App).use(pinia).mount('#app');

app.vue

<script setup>
import { useUserStore } from './stores/user';
const userStore = useUserStore();

const add = () => {
  userStore.user.age = userStore.user.age + 1;
  axios.get('/');
  userStore.$persist();
};
</script>

<template>
  <div>
    {{ userStore.user.age }}
  </div>
  <button @click="add">Add</button>
</template>

Got error

image

I know it can move into axios.interceptors.request inner, but useUserStore(pinia) can be work, why pinia-plugin-persistedstate cannot. I think it maybe a bug.

And I just reproduced the problem using Axios. In fact, in my project, there are many places where the store is created before Pinia. All of them use the way of useUserStore(pinia). If modifications are to be made, this change will be very large.

Reproduction

https://stackblitz.com/edit/vitejs-vite-tgnzng?file=src%2Faxios.js

System Info

System:
    OS: macOS 15.0
    CPU: (8) arm64 Apple M1
    Memory: 99.66 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.17.0 - ~/.nvm/versions/node/v20.17.0/bin/node
    pnpm: 9.7.0 - ~/.nvm/versions/node/v20.17.0/bin/pnpm
  Browsers:
    Chrome: 130.0.6723.70
    Edge: 130.0.2849.56
    Safari: 18.0

Used Package Manager

npm

Validations

prazdevs commented 4 weeks ago

Hi, thanks for the reproduction, it helped me pin what is probably the issue.

I think it comes from the way Pinia itself handles plugins. As stated in the docs (here), Pinia plugins are applied ONLY after pinia is passed to the app. In your case, Pinia is instantiated and used before the app (you need to pass it the Pinia instance explicitely), so the persistedstate plugin is not part of it because of that.

It can be confirmed by this code from pinia, which defers plugins if there is no Vue app instance available.

I will try to investigate a bit if that can be fixed/worked around from our plugin, but I doubt it.

I can see two solutions for you:

Hopefully this helps you a bit 🙏

seepine commented 4 weeks ago

Yes, I tried to customize the plugin,it cannot be applied to the store created before.

pinia.use(context => {
  console.log(context)
})

Any setTimeout of pinia._s can got all store, but this is not a good idea.

setTimeout(() => {

  pinia._s.forEach(store => {
    console.log(store)
  })
}, 200)