Skip to main content

[Pinia] reset store

6/3/2025 發布

在 Option API 的環境中,可以使用 $reset 來將 store 的狀態重置到初始值。
但在 Composition API 中 store 的實例就沒有這個方法了,
這個問題在 GitHub Issues 上也有被討論到,在留言中看到有大大想出了好方法!

Plugin

大大的文章中示範的方法也很簡短。
Pinia 設計了 plugin 的方式,讓我們可以對 store 掛載自定義的靜態屬性。

createPinia 時可以存取 pinia app 的實例並使用 .use 將我們寫好的方法掛載上去,
之後所有的 store 就會在實例化時把指定要掛載的方法或屬性一起加入:

// 自定義的 plugin
export default function resetStorePlugin({ store }: { store: Store }) {
const initialState = cloneDeep(store.$state); // lodash 的 cloneDeep
store.$reset = () => store.$patch(cloneDeep(initialState));
}

// 在 main.ts 中進行掛載
const pinia = createPinia();
pinia.use(resetStorePlugin);

之後就可以在任意能夠存取 store 的地方一如往常呼叫 $reset,例如在按鈕事件中:

<script setup lang="ts">
import { useMyStore } from '@/store'

const store = useMyStore();
</script>

<template>
<p>{{ store.count }}</>
<button type="button" @click="store.count++">+</button>
<button type="button"@click="store.count--">-</button>
<button type="button"@click="store.$reset()">Reset</button>
</template>

重置所有 store

目前我手上的專案有這個需求,所以研究了一下怎麼存取已經存在的 store 實例。

官方有提供 getActivePinia 這個 API,但需要存取裡面的私有屬性 _s
才能拿到 store 的實例集合。

所以另外設計了一個 plugin,讓 store 實例化時被參照到 trackedStores 這個 Set 裡面,
resetAllStores 來遍歷 trackedStores 中所有 store,執行前面掛載好的 $reset

// 記錄所有實例化的 store
const trackedStores = new Set<Store>();

export function trackStorePlugin({ store }: { store: Store }) {
trackedStores.add(store);
}

export function getAllTrackedStores() {
return Array.from(trackedStores);
}

// 重置所有 store 為初始狀態
export function resetAllStores() {
const stores = getAllTrackedStores();

for (const store of stores) {
store.$reset?.();
}
}

掛載到 Pinia 實例上:

const pinia = createPinia();
pinia.use(resetStorePlugin);
pinia.use(trackStorePlugin);
info

plugin 除了掛載到 Pinia 實例上來提供所有 store 存取,也可以針對個別的 store 進行掛載,
只要留意設計函式時必須符合 PiniaPluginContext 這個型別。


優化

當全域的 plugin 變多時,可以統一整理好再使用 .use 掛載,
不過要記得調整 plugin 的函式參數,完整的程式碼如下:

import { cloneDeep } from 'lodash-es';

import type { PiniaPluginContext, Store } from 'pinia';

// 掛載 $reset 方法到 store 上
export function resetStorePlugin(store: Store) {
const initialState = cloneDeep(store.$state);
store.$reset = () => store.$patch(cloneDeep(initialState));
}

// 記錄所有實例化的 store
const trackedStores = new Set<Store>();

export function trackStorePlugin(store: Store) {
trackedStores.add(store);
}

export function getAllTrackedStores() {
return Array.from(trackedStores);
}

// 重置所有 store 為初始狀態
export function resetAllStores() {
const stores = getAllTrackedStores();

for (const store of stores) {
store.$reset?.();
}
}

// 在 pinia 實例化時,一次性掛載全域的 plugin
export function customPiniaPlugins({ store }: PiniaPluginContext) {
resetStorePlugin(store);
trackStorePlugin(store);
}

// 在 main.ts 掛載
const pinia = createPinia();
pinia.use(customPiniaPlugins);

參考資料