]> git.ipfire.org Git - thirdparty/vuejs/pinia.git/commitdiff
fix(subscribe): remove subscription when unmounted
authorEduardo San Martin Morote <posva13@gmail.com>
Sat, 10 Apr 2021 15:13:25 +0000 (17:13 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Sat, 10 Apr 2021 15:20:46 +0000 (17:20 +0200)
__tests__/lifespan.spec.ts
__tests__/subscriptions.spec.ts
src/store.ts

index af84547b85c0c47e4ef0b70b7e8b7c4a7199f1a5..869868df9c0e18a0379f0d6603d5323a55fdf812 100644 (file)
@@ -39,7 +39,6 @@ describe('Store Lifespan', () => {
 
   it.skip('what', async () => {
     const localVue = createLocalVue()
-    localVue.use(VueCompositionAPI)
     const n = 0
     const Component = defineComponent({
       render: (h) => h('p'),
index 5aabbbdc43d7c57c413cff7fb80bfc6826bf9c34..3277360de481f1a7ff64049a28816c37dc745401 100644 (file)
@@ -1,5 +1,13 @@
+import { nextTick } from '@vue/composition-api'
+import { createLocalVue, mount } from '@vue/test-utils'
 import Vue from 'vue'
-import { defineStore, setActivePinia, createPinia, Pinia } from '../src'
+import {
+  defineStore,
+  setActivePinia,
+  createPinia,
+  Pinia,
+  PiniaPlugin,
+} from '../src'
 
 describe('Subscriptions', () => {
   let pinia: Pinia
@@ -57,6 +65,9 @@ describe('Subscriptions', () => {
     })
 
     it('triggers subscribe only once', async () => {
+      const pinia = createPinia()
+      pinia.Vue = Vue
+      setActivePinia(pinia)
       const s1 = useStore()
       const s2 = useStore()
 
@@ -74,5 +85,50 @@ describe('Subscriptions', () => {
       expect(spy1).toHaveBeenCalledTimes(1)
       expect(spy2).toHaveBeenCalledTimes(1)
     })
+
+    it('removes on unmount', async () => {
+      const pinia = createPinia()
+      pinia.Vue = Vue
+      const spy1 = jest.fn()
+      const spy2 = jest.fn()
+
+      const localVue = createLocalVue()
+      localVue.use(PiniaPlugin)
+
+      const wrapper = mount(
+        {
+          setup() {
+            const s1 = useStore()
+            s1.$subscribe(spy1)
+          },
+          template: `<p/>`,
+        },
+        { pinia, localVue }
+      )
+
+      const s1 = useStore()
+      const s2 = useStore()
+
+      s2.$subscribe(spy2)
+
+      expect(spy1).toHaveBeenCalledTimes(0)
+      expect(spy2).toHaveBeenCalledTimes(0)
+
+      s1.name = 'Edu'
+
+      expect(spy2).toHaveBeenCalledTimes(1)
+      expect(spy1).toHaveBeenCalledTimes(1)
+
+      s1.$patch({ name: 'a' })
+      expect(spy1).toHaveBeenCalledTimes(2)
+      expect(spy2).toHaveBeenCalledTimes(2)
+
+      wrapper.destroy()
+      await nextTick()
+
+      s1.$patch({ name: 'b' })
+      expect(spy1).toHaveBeenCalledTimes(2)
+      expect(spy2).toHaveBeenCalledTimes(3)
+    })
   })
 })
index 491d1e13a856b3be6ffc9dbb02cf18c9f31110d1..e6453222ffdc1d8b8c08b88b397af896da3a1ceb 100644 (file)
@@ -6,6 +6,7 @@ import {
   getCurrentInstance,
   markRaw,
   inject,
+  onUnmounted,
 } from '@vue/composition-api'
 import {
   StateTree,
@@ -141,13 +142,19 @@ function initStore<Id extends string, S extends StateTree>(
       }
     )
 
-    return () => {
+    const removeSubscription = () => {
       const idx = subscriptions.indexOf(callback)
       if (idx > -1) {
         subscriptions.splice(idx, 1)
         stopWatcher()
       }
     }
+
+    if (getCurrentInstance()) {
+      onUnmounted(removeSubscription)
+    }
+
+    return removeSubscription
   }
 
   function $reset() {