]> git.ipfire.org Git - thirdparty/vuejs/pinia.git/commitdiff
fix: detach stores creation from currentInstance
authorEduardo San Martin Morote <posva13@gmail.com>
Tue, 29 Sep 2020 07:45:42 +0000 (09:45 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Tue, 29 Sep 2020 07:45:42 +0000 (09:45 +0200)
__tests__/store.spec.ts
src/env.ts [new file with mode: 0644]
src/store.ts
src/withScope.ts [new file with mode: 0644]

index d8f15053e2b8dfbc7123181a8347e7cae04a83bc..6f3be1f3d8dfbd8102ffec847cc97c1eaac1feb7 100644 (file)
@@ -1,4 +1,9 @@
-import { defineStore, setActiveReq, setStateProvider } from '../src'
+import {
+  createPinia,
+  defineStore,
+  setActiveReq,
+  setStateProvider,
+} from '../src'
 import { mount } from '@vue/test-utils'
 
 describe('Store', () => {
@@ -150,18 +155,25 @@ describe('Store', () => {
     )
   })
 
-  it.skip('should outlive components', () => {
+  it('should outlive components', () => {
     let store: ReturnType<typeof useStore> | undefined
 
-    const wrapper = mount({
-      setup() {
-        store = useStore()
+    const wrapper = mount(
+      {
+        setup() {
+          store = useStore()
 
-        return { store }
-      },
+          return { store }
+        },
 
-      template: `a: {{ store.a }}`,
-    })
+        template: `a: {{ store.a }}`,
+      },
+      {
+        global: {
+          plugins: [createPinia()],
+        },
+      }
+    )
 
     expect(wrapper.html()).toBe('a: true')
 
diff --git a/src/env.ts b/src/env.ts
new file mode 100644 (file)
index 0000000..53538e8
--- /dev/null
@@ -0,0 +1 @@
+export const IS_CLIENT = typeof window !== 'undefined'
index 88949c6ef00a8714ded79289c4ad60b61fb56ac4..7832df2182e1eb386740490e3b891f74045acc56 100644 (file)
@@ -27,8 +27,8 @@ import {
   piniaSymbol,
 } from './rootStore'
 import { addDevtools } from './devtools'
-
-const IS_CLIENT = typeof window !== 'undefined'
+import { IS_CLIENT } from './env'
+import { withScope } from './withScope'
 
 function innerPatch<T extends StateTree>(
   target: T,
@@ -214,8 +214,16 @@ export function defineStore<
     if (!store) {
       stores.set(
         id,
-        // @ts-ignore
-        (store = buildStore(id, state, getters, actions, getInitialState(id)))
+        (store = withScope(
+          () =>
+            buildStore(
+              id,
+              state,
+              getters as Record<string, Method> | undefined,
+              actions as Record<string, Method> | undefined,
+              getInitialState(id)
+            ) as Store<Id, S, G, A>
+        ))
       )
 
       if (IS_CLIENT && __DEV__ /*|| __FEATURE_PROD_DEVTOOLS__*/) {
diff --git a/src/withScope.ts b/src/withScope.ts
new file mode 100644 (file)
index 0000000..8631513
--- /dev/null
@@ -0,0 +1,19 @@
+import { createApp } from 'vue'
+import { IS_CLIENT } from './env'
+
+export function withScope<T>(factory: () => T): T {
+  if (__BROWSER__ && IS_CLIENT) {
+    let store: T
+    createApp({
+      setup() {
+        store = factory()
+        return () => null
+      },
+    }).mount(document.createElement('div'))
+    // TODO: collect apps to be unmounted when the main app is unmounted
+    return store!
+  } else {
+    // no need to wrap with an app on SSR
+    return factory()
+  }
+}