Today I will share some Pinia Plugins I have found to help you manage application states more efficiently.

pinia-plugin-persistedstate

If you want to synchronize localStorage / sessionStorage with pinia, you can try pinia-plugin-persistedstate. It also supports custom persistence methods and SSR.

Pinia Plugin Persistedstate

Here is a simple example:

npm install pinia-plugin-persistedstate
import { createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);
export const useStore = defineStore("main", {
state: () => ({ someState: "hello pinia" }),
persist: true,
});

pinia-plugin-persist

If you want to keep the state persistent in simple scenarios and it is a small project that does not require complex configuration, you may try the more lightweight pinia-plugin-persist.

npm install pinia-plugin-persist
import { createApp } from "vue";
import { createPinia } from "pinia";
import piniaPersist from "pinia-plugin-persist";
const pinia = createPinia();
pinia.use(piniaPersist);
createApp({}).use(pinia).mount("#app");

pinia-plugin-debounce

When you think that frequent triggering of Action affects performance, you can try this library - pinia-plugin-debounce, which supports real-time search and form debouncing!

Pinia Debounce

Here is a simple example:

npm install @pinia/plugin-debounce
import { createPinia } from "pinia";
import debounce from "lodash.debounce";
import piniaPluginDebounce from "@pinia/plugin-debounce";
const pinia = createPinia();
pinia.use(piniaPluginDebounce({ debounce }));
export const useSearchStore = defineStore("search", {
actions: {
searchContacts() {
// Search logic
},
},
debounce: {
searchContacts: 300, // 300ms debounce
},
});

pinia-plugin-orm

When you need to do ORM mapping for asynchronous data, such as user lists and permission models with complex data relationship management, you can use this library, Pinia ORM

Pinia ORM

Here is a simple example:

npm install pinia-plugin-orm
import { PiniaORM } from "pinia-plugin-orm";
export default (pinia: Pinia) => {
pinia.use(PiniaORM.install());
};
// stores/User.ts
import { defineStore } from "pinia";
import { Model } from "pinia-plugin-orm";
export class User extends Model {
static entity = "users";
static fields() {
return {
id: this.attr(null),
name: this.string(""),
email: this.string(""),
role: this.belongsTo(Role, "roleId"),
};
}
}
export const useUserStore = defineStore("users", {
actions: {
async fetchUsers() {
const data = await fetch("/api/users").then((res) => res.json());
User.insert({ data });
},
},
});
// stores/Role.ts
import { Model } from "pinia-plugin-orm";
export class Role extends Model {
static entity = "roles";
static fields() {
return {
id: this.attr(null),
name: this.string(""),
};
}
}

and then you can use it like this:

const users = User.query().with("role").get();

pinia-plugin-shared-state

pinia-plugin-shared-state allows sharing Pinia Store states between multiple windows or tabs by synchronizing data through localStorage or BroadcastChannel.

This is the official demo that can be opened in multiple tabs: https://wobsoriano.github.io/pinia-shared-state

Here is a simple example:

npm install pinia-plugin-shared-state
import { createPinia } from "pinia";
import { createSharedState } from "pinia-plugin-shared-state";
const pinia = createPinia();
pinia.use(
createSharedState({
enable: true,
initialize: true,
})
);
export const useAuthStore = defineStore("auth", {
state: () => ({ user: null }),
actions: {
async login() {
const response = await fetch("/api/login");
this.user = await response.json();
},
},
share: {
enable: true,
},
});

pinia-undo

pinia-undo can be used to track the history of state changes in Pinia stores, allowing you to undo and redo actions. It is a simple and effective way to manage state changes in your application.

Here is a simple example:

pnpm add pinia pinia-undo
import { PiniaUndo } from "pinia-undo";
const pinia = createPinia();
pinia.use(PiniaUndo);
const useCounterStore = defineStore({
id: "counter",
state: () => ({
count: 10,
}),
actions: {
increment() {
this.count++;
},
},
});
const counterStore = useCounterStore();
counterStore.undo(); // { count: 10 }
counterStore.redo(); // { count: 10 }
counterStore.increment(); // { count: 11 }
counterStore.increment(); // { count: 12 }
counterStore.undo(); // { count: 11 }
counterStore.undo(); // { count: 10 }
counterStore.undo(); // { count: 10 }
counterStore.redo(); // { count: 11 }

Finally

That's all for today's sharing. Thank you for reading.