-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pinia persisted state: storages (session storage) #356
Comments
I've played around with this plugin a few days ago. Instead of using When a pre-rendered page is fully loaded by the browser, the store is primed with the server-initialized state. But when navigating to subsequent pages (you are in SPA mode now), there is no server-initialized state. Edit: This part of the comment was irrelevant. // src/stores/index.js
import { store as createStore } from 'quasar/wrappers';
import { createPinia } from 'pinia';
import { createPersistedState } from 'pinia-plugin-persistedstate';
export default createStore((/* { ssrContext } */) => {
const pinia = createPinia();
if (!import.meta.env.SSR) {
pinia.use(createPersistedState({
auto: true,
beforeRestore: ({ store }) => {
if (store.$state.hasChanged === true) {
store.$persist();
}
},
}));
}
return pinia;
}); // src/stores/example.js
import { defineStore } from 'pinia';
export const useExampleStore = defineStore('example', {
state: () => ({
counter: 0,
data: null,
hasChanged: false,
}),
getters: {
doubleCount: (state) => state.counter * 2,
},
actions: {
increment() {
this.counter += 1;
this.hasChanged = true;
},
async fetchData() {
this.data = await (await fetch('https://someapi.com')).json();
this.hasChanged = true;
},
},
}); // src/components/ExampleComponent.vue
<template>
<div>
<div>Direct store</div>
<!-- Read the state value directly -->
<div>{{ store.counter }}</div>
<pre>{{ store.data }}</pre>
<!-- Use getter directly -->
<div>{{ store.doubleCount }}</div>
<!-- Manipulate state directly -->
<q-btn @click="store.counter--">-</q-btn>
<!-- Use an action -->
<q-btn @click="store.increment()">+</q-btn>
</div>
</template>
<script>
import { useExampleStore } from 'stores/example';
import { onBeforeMount, onServerPrefetch } from 'vue';
export default {
setup() {
const store = useExampleStore();
// this hook is executed at server side only
onServerPrefetch(async () => {
await store.fetchData();
});
// this hook is executed at client-side only
onBeforeMount(async () => {
if (store.hasChanged === false) {
await store.fetchData();
}
});
return {
store,
};
},
};
</script> |
The use of ssg/ssr and client-side persistent state leads to two distinct sources of state. You have one source initialized at build-time, and an other from a storage at client-side. If these two sources differ, there will be a client-side warning about the hydration mismatch. You can enable the Quasar manualStoreHydration option, but you'll still have hydration mismatch. This is because the pre-rendered content will have the initial state, which may differ from the persistent state. There are two ways of solving this problem:
The disadvantage of these two solutions is that you'll have to manage a kind of loading state, rather than having content that changes abruptly. For the second solution, I found a not-so-clean way of doing it by using the 'onMounted' hook in the root component "App.vue": // src/App.vue
<template>
<router-view />
</template>
<script setup>
import { getActivePinia } from 'pinia';
import { createPersistedState } from 'pinia-plugin-persistedstate';
import { onMounted } from 'vue';
if (process.env.CLIENT) {
const pinia = getActivePinia();
pinia?.use((context) => {
onMounted(() => {
createPersistedState({
auto: true,
beforeRestore: () => {
console.log('beforeRestore');
},
afterRestore: () => {
console.log('afterRestore');
},
})(context);
});
});
}
</script> // src/store/index.js
import { store as createStore } from 'quasar/wrappers';
import { createPinia } from 'pinia';
export default createStore(() => createPinia()); |
Hi, thanks so much for this project! I manage to get most of my project running, but I can't seem to manage to use
pinia-plugin-persistedstate
and its sessionStorage without getting hacky. Is there any config part that I missed out on or is that something in progress?I've added
if (typeof window !== 'undefined') pinia.use(piniaPluginPersistedstate)
in the store config, and added{ persist: typeof window === 'undefined' ? false : { storage: sessionStorage, }, }
in my individual stores to make sure they're running in the client side. Despite causing glitches, I guess it works. Just wondered if there are configs for pinia or rehydration. Thank you again!The text was updated successfully, but these errors were encountered: