Closed BenJackGill closed 2 years ago
I dont really see what could be wrong, but I played a bit with the reprod repo, and in the vue devtools, there is no event related to pinia that is fired. This is weird and I dont really understand why, but that could be related to the issue since we subscribe to state mutations (like the devtools). My guess is there is smth with quasar, and i never used it so I can't help much atm. I'll try to look further, or if anyone has an idea.
Ok thanks, you have set me on the right path because I have narrowed it down to being a problem with my Quasar boot file.
Also I realised the opening post wasn't very clear, so I have updated it to reflect the current situation.
Will post an update here if I find one!
Hi, Quasar core team member here 👋
It's about Pinia's limitation about using plugins before the app is initialized: https://github.com/quasarframework/quasar/discussions/12736#discussioncomment-2338508
We will release first-party Pinia support soon, and mention this limitation on our docs, pointing to the Pinia documentation.
Quasar Framework has first-party Pinia support since @quasar/app-vite-v1.0.0-beta.1 and @quasar/app-webpack-v3.4.0.
This limitation is by-passed by passing the store to the app instance earlier since @quasar/app-vite-v1.0.0-beta.3 and @quasar/app-webpack-v3.4.3.
So, I think this issue can be closed now. But, I think something like createQuasarPersistedState
that uses LocalStorage/SessionStorage and/or Cookies plugins would be really cool. It can be supported with a boot file example(similar to Nuxt's plugins). These great samples from @TobyMosque might be used as a reference implementation:
The boot file that contains an alternative implementation to pinia-plugin-persistedstate
:
https://github.com/TobyMosque/quasar-v2-ssr-pinia/blob/47d05b5595b42a2c77f5e502f2ffee2b0be76a3d/src/boot/persist-store.ts
Individual stores using different storage plugins:
https://github.com/TobyMosque/quasar-v2-ssr-pinia/blob/47d05b5595b42a2c77f5e502f2ffee2b0be76a3d/src/stores/persisted-localstorage.ts
https://github.com/TobyMosque/quasar-v2-ssr-pinia/blob/47d05b5595b42a2c77f5e502f2ffee2b0be76a3d/src/stores/persisted-sessionstorage.ts
https://github.com/TobyMosque/quasar-v2-ssr-pinia/blob/47d05b5595b42a2c77f5e502f2ffee2b0be76a3d/src/stores/persisted-cookie.ts
started working on a helper for Quasar, i'll try to expose 3:
👍
localstorage
and sessionstorage
will work out of box, so u don't need to worry.
regarding the cookies
, i was able to make Pinia Persisted State Plugin work with the Quasar Cookies Plugin, but my solution is nesty, to not say ugly.
first, u'll need a fake storage:
import { StorageLike } from 'pinia-plugin-persistedstate';
export const cookieStorage: StorageLike = {
getItem(key: string) {
return '';
},
setItem(key: string, value: string) {
return;
},
};
we just need something (the fake storage) to import in the stores, like this:
import { defineStore } from 'pinia';
import { cookieStorage } from './storages';
export const useAppStore = defineStore('app', {
state: () => ({
token: '',
}),
persist: {
storage: cookieStorage,
},
});
so, we can replace that fake storage by the real one in a boot
or in the stores/index
import { store } from 'quasar/wrappers';
import { createPinia } from 'pinia';
import PiniaPersistedStatePlugin from 'pinia-plugin-persistedstate';
import { cookieStorage } from './storages';
import { Cookies } from 'quasar';
export default store(({ ssrContext }) => {
const pinia = createPinia();
// You can add Pinia plugins here
// pinia.use(SomePiniaPlugin)
const cookies = process.env.SERVER ? Cookies.parseSSR(ssrContext) : Cookies; // otherwise we're on client
pinia.use(({ options }) => {
if (!options.persist || typeof options.persist === 'boolean') {
return;
}
if (options.persist.storage === cookieStorage) {
options.persist.storage = {
getItem(key: string) {
return JSON.stringify(cookies.get(key));
},
setItem(key: string, value: string) {
const obj = JSON.parse(value);
cookies.set(key, obj, { path: '/', sameSite: 'Lax', secure: true });
},
};
}
});
pinia.use(PiniaPersistedStatePlugin);
return pinia;
});
This would be done before the PiniaPersistedStatePlugin be configured.
here the source: https://github.com/TobyMosque/ws-auth-samples-frontend/tree/persist-after/src/stores
yeah i think i took inspiration from some of your repos as im very unfamiliar with Quasar. Idea was to provide a helper as simple to use as this :
import { boot } from "quasar/wrappers";
import { Cookies } from "quasar";
import {
createQuasarCookiesPersistedState
} from "pinia-plugin-persistedstate/quasar";
export default boot(({ store, ssrContext }) => {
store.use(createQuasarCookiesPersistedState(Cookies, ssrContext));
});
Kinda like what we did for Nuxt
maybe as a plugin.:
# the package will be named as quasar-app-extension-pinia-persistedstate
quasar ext add pinia-persistedstate
this extension will install the PiniaPersistedStatePlugin, the Cookies Plugins and register the boots. so, in the dev land:
import { defineStore } from 'pinia';
# pinia-plugin-persistedstate/quasar is an alias to quasar-app-extension-pinia-persistedstate
import { CookieStorage, /*LocalStorage, SessionStorage,IndexedStorage*/ } from 'pinia-plugin-persistedstate/quasar';
export const useAppStore = defineStore('app', {
state: () => ({
token: '',
}),
persist: {
storage: CookieStorage,
},
});
more about quasar extensions: https://quasar.dev/app-extensions/tips-and-tricks/inject-quasar-plugin
that's fairly interesting. i never use quasar (cause its wayyy too heavy for what i do with vue). But whenever i have time i'll look into maybe making a quasar plugin as you suggest! (or someone can try to do it 😄)
thanks a lot!
cause its wayyy too heavy for what i do with vue.
Fallacies I hear every day ;D Quasar is suitable for all project sizes, even the smallest ones.
v2.1.0
now offers quasar helpers. Docs are also updated with how to use it!
I kept it iso with the way the Nuxt helper is made for now.
Closing this for now? feel free to reopen if you feel like something is off/odd/broken
localstorage
andsessionstorage
will work out of box, so u don't need to worry. regarding thecookies
, i was able to make Pinia Persisted State Plugin work with the Quasar Cookies Plugin, but my solution is nesty, to not say ugly.first, u'll need a fake storage:
import { StorageLike } from 'pinia-plugin-persistedstate'; export const cookieStorage: StorageLike = { getItem(key: string) { return ''; }, setItem(key: string, value: string) { return; }, };
we just need something (the fake storage) to import in the stores, like this:
import { defineStore } from 'pinia'; import { cookieStorage } from './storages'; export const useAppStore = defineStore('app', { state: () => ({ token: '', }), persist: { storage: cookieStorage, }, });
so, we can replace that fake storage by the real one in a
boot
or in thestores/index
import { store } from 'quasar/wrappers'; import { createPinia } from 'pinia'; import PiniaPersistedStatePlugin from 'pinia-plugin-persistedstate'; import { cookieStorage } from './storages'; import { Cookies } from 'quasar'; export default store(({ ssrContext }) => { const pinia = createPinia(); // You can add Pinia plugins here // pinia.use(SomePiniaPlugin) const cookies = process.env.SERVER ? Cookies.parseSSR(ssrContext) : Cookies; // otherwise we're on client pinia.use(({ options }) => { if (!options.persist || typeof options.persist === 'boolean') { return; } if (options.persist.storage === cookieStorage) { options.persist.storage = { getItem(key: string) { return JSON.stringify(cookies.get(key)); }, setItem(key: string, value: string) { const obj = JSON.parse(value); cookies.set(key, obj, { path: '/', sameSite: 'Lax', secure: true }); }, }; } }); pinia.use(PiniaPersistedStatePlugin); return pinia; });
This would be done before the PiniaPersistedStatePlugin be configured.
here the source: https://github.com/TobyMosque/ws-auth-samples-frontend/tree/persist-after/src/stores
thanks aloooot man <3
I'm trying to use this Pinia Plugin in my Quasar app (Vue 3 / TypeScript).
Out of the box everything works fine.
But when using a Quasar boot file the persisted state stops working. Refreshing the page wipes all the new values away.
I don't know why the boot file breaks the persisted state plugin, but I have narrowed the culprit down to a single line...
This is how I am using Pinia with Quasar and adding the plugin:
src/store/index.ts
And this is what my Pinia store looks like:
src/store/user.ts
Here is an example front-end page for fetching and setting the firstName:
src/pages/index.vue
Up to this point everything works fine.
I can set firstName to the Pinia store, refresh the page, and the new name is still in Pinia.
But when trying to use
const userStore = useUserStore(store)
inside a boot file like the example below, the persisted state stops working:src/boot/auth.ts
Any idea what's going on? And how to fix it?
I think this plugin is much cleaner than using the alternate LocalStorage persisted state solution so I would love to get it working with Quasar.