Closed swuecho closed 3 months ago
system 2024-05-13T01:08:53Z: You are expert on frontend development}
user 2024-05-14T03:28:01Z: create a pinia store plugins that sync change to localStorage
assistant 2024-05-14T03:28:13Z: Pinia is an excellent state management library for Vue.js that allows you to create stores to manage your state. To sync the state changes with localStorage, you can create a Pinia plugin. Here's a step-by-step guide to creating a Pinia plugin that syncs changes to localStorage:
First, if you haven't already installed Pinia, you need to install it:
npm install pinia
Create a file (e.g., piniaLocalStoragePlugin.js
or piniaLocalStoragePlugin.ts
for TypeScript) and define the plugin.
// piniaLocalStoragePlugin.js
export default function createLocalStoragePlugin(options) {
return (context) => {
const { store } = context;
// Load stored state from localStorage
const storedStateJSON = localStorage.getItem(`pinia-${store.$id}`);
if (storedStateJSON) {
store.$patch(JSON.parse(storedStateJSON));
}
// Subscribe to store changes and sync with localStorage
store.$subscribe((mutation, state) => {
localStorage.setItem(`pinia-${store.$id}`, JSON.stringify(state));
});
};
}
// piniaLocalStoragePlugin.ts
import { PiniaPluginContext, StateTree } from 'pinia';
export default function createLocalStoragePlugin(options?: any) {
return (context: PiniaPluginContext) => {
const { store } = context;
// Load stored state from localStorage
const storedStateJSON = localStorage.getItem(`pinia-${store.$id}`);
if (storedStateJSON) {
store.$patch(JSON.parse(storedStateJSON));
}
// Subscribe to store changes and sync with localStorage
store.$subscribe((mutation, state: StateTree) => {
localStorage.setItem(`pinia-${store.$id}`, JSON.stringify(state));
});
};
}
Now, you need to integrate the plugin into your Pinia setup. Assuming you are using Vue 3, configure your main application entry file (e.g., main.js
or main.ts
).
// main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import createLocalStoragePlugin from './piniaLocalStoragePlugin';
const app = createApp(App);
const pinia = createPinia();
pinia.use(createLocalStoragePlugin());
app.use(pinia);
app.mount('#app');
// main.ts
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import createLocalStoragePlugin from './piniaLocalStoragePlugin';
const app = createApp(App);
const pinia = createPinia();
pinia.use(createLocalStoragePlugin());
app.use(pinia);
app.mount('#app');
Create a Pinia store to see the plugin in action:
// stores/counter.js or stores/counter.ts
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++;
},
decrement() {
this.count--;
},
},
});
Finally, use the store within a Vue component to see the state being synced with localStorage.
<!-- CounterComponent.vue -->
<template>
<div>
<p>Count: {{ counter.count }}</p>
<button @click="counter.increment">Increment</button>
<button @click="counter.decrement">Decrement</button>
</div>
</template>
<script>
import { useCounterStore } from '../stores/counter';
export default {
setup() {
const counter = useCounterStore();
return { counter };
},
};
</script>
That's it! Now whenever the state changes, it will be synchronized with localStorage. When you refresh the page, the state will be rehydrated from localStorage.
https://pinia.vuejs.org/core-concepts/plugins.html#Calling-subscribe-inside-plugins