]> git.ipfire.org Git - thirdparty/vuejs/pinia.git/commitdiff
feat: destroy a store with $dispose (#597)
authorEduardo San Martin Morote <posva@users.noreply.github.com>
Thu, 19 Aug 2021 11:01:18 +0000 (13:01 +0200)
committerGitHub <noreply@github.com>
Thu, 19 Aug 2021 11:01:18 +0000 (13:01 +0200)
packages/pinia/__tests__/store.spec.ts
packages/pinia/src/devtools/plugin.ts
packages/pinia/src/store.ts
packages/pinia/src/types.ts

index 7e8d1731074615553cb6539d9e48b6371e8f5571..a0c06ff51d2def380deca2179fe58c8d3d6d7b9e 100644 (file)
@@ -303,4 +303,27 @@ describe('Store', () => {
     expect(One.text()).toBe('1')
     expect(Two.text()).toBe('1')
   })
+
+  it('can be disposed', () => {
+    const pinia = createPinia()
+    const useStore = defineStore({
+      id: 'main',
+      state: () => ({ n: 0 }),
+    })
+
+    const store = useStore(pinia)
+    const spy = jest.fn()
+
+    store.$subscribe(spy, { flush: 'sync' })
+    pinia.state.value.main.n++
+    expect(spy).toHaveBeenCalledTimes(1)
+
+    expect(useStore()).toBe(store)
+    store.$dispose()
+    pinia.state.value.main.n++
+
+    expect(spy).toHaveBeenCalledTimes(1)
+
+    expect(useStore()).not.toBe(store)
+  })
 })
index 0ca6bf81466d18d1f08d05d4e4d4dfd7659f4442..04fd9d001b62c2b1750e3247e2f62f8b20bf42ca 100644 (file)
@@ -414,11 +414,20 @@ function addStoreToDevtools(app: App, store: StoreGeneric) {
         api.sendInspectorState(INSPECTOR_ID)
       })
 
+      const { $dispose } = store
+      store.$dispose = () => {
+        $dispose()
+        api.notifyComponentUpdate()
+        api.sendInspectorTree(INSPECTOR_ID)
+        api.sendInspectorState(INSPECTOR_ID)
+        toastMessage(`Disposed "${store.$id}" store ðŸ—‘`)
+      }
+
       // trigger an update so it can display new registered stores
       api.notifyComponentUpdate()
       api.sendInspectorTree(INSPECTOR_ID)
       api.sendInspectorState(INSPECTOR_ID)
-      toastMessage(`"${store.$id}" store installed`)
+      toastMessage(`"${store.$id}" store installed ðŸ†•`)
     }
   )
 }
index c9b9428c0d6d3995a9b74905066345c136ddd8f4..aca79319d9d9b35df8b10636e5cf8429ea535a9f 100644 (file)
@@ -269,6 +269,13 @@ function createSetupStore<
       }
     : noop
 
+  function $dispose() {
+    scope.stop()
+    subscriptions = []
+    actionSubscriptions = []
+    pinia._s.delete($id)
+  }
+
   /**
    * Wraps an action to handle subscriptions.
    *
@@ -448,6 +455,7 @@ function createSetupStore<
 
       return removeSubscription
     },
+    $dispose,
   } as StoreWithState<Id, S, G, A>
 
   const store: Store<Id, S, G, A> = reactive(
index c5a5ff86975dffe51e11ac6a15b6ed5510dd2b16..afc1872b274865cedab4043865d1cd8f6c126bfb 100644 (file)
@@ -414,6 +414,14 @@ export interface StoreWithState<
     callback: StoreOnActionListener<Id, S, G, A>,
     detached?: boolean
   ): () => void
+
+  /**
+   * Stops the associated effect scope of the store and remove it from the store
+   * registry. Plugins can override this method to cleanup any added effects.
+   * e.g. devtools plugin remove its listeners and stops displaying it from
+   * devtools.
+   */
+  $dispose(): void
 }
 
 /**