From: Eduardo San Martin Morote Date: Fri, 3 Sep 2021 14:25:25 +0000 (+0200) Subject: refactor: avoid double hydration in setup stores X-Git-Tag: @pinia/nuxt@0.0.2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=214ee7ea32fe71ef4a40f1c42c94b5af7310fb7f;p=thirdparty%2Fvuejs%2Fpinia.git refactor: avoid double hydration in setup stores --- diff --git a/packages/pinia/__tests__/ssr.spec.ts b/packages/pinia/__tests__/ssr.spec.ts index 96502c16..6bd63cbc 100644 --- a/packages/pinia/__tests__/ssr.spec.ts +++ b/packages/pinia/__tests__/ssr.spec.ts @@ -1,8 +1,8 @@ /** * @jest-environment node */ -import { createPinia } from '../src' -import { Component, createSSRApp, inject } from 'vue' +import { createPinia, defineStore } from '../src' +import { Component, createSSRApp, inject, ref, computed } from 'vue' import { renderToString, ssrInterpolate } from '@vue/server-renderer' import { useUserStore } from './pinia/stores/user' import { useCartStore } from './pinia/stores/cart' @@ -109,4 +109,74 @@ describe('SSR', () => { ]" `) }) + + describe('Setup Store', () => { + const useStore = defineStore('main', () => { + const count = ref(0) + const name = ref('Eduardo') + const double = computed(() => count.value * 2) + + function increment() { + count.value++ + } + + return { name, count, double, increment } + }) + + const App = { + ssrRender(ctx: any, push: any, _parent: any) { + push( + `` + ) + }, + setup() { + const store = useStore() + store.count++ + + return { store } + }, + } + + it('works', async () => { + const { pinia, app } = createMyApp(App) + + pinia.state.value.main = { + count: 2, + name: 'Eduardo', + } + + expect(await renderToString(app)).toBe('') + }) + + it('store can be changed before rendering', async () => { + const { pinia, app } = createMyApp(App) + + pinia.state.value.main = { + count: 2, + name: 'Eduardo', + } + + const store = useStore(pinia) + store.count = 10 + + expect(await renderToString(app)).toBe('') + }) + + it('pinia can be changed before rendering', async () => { + const { pinia, app } = createMyApp(App) + + pinia.state.value.main = { + count: 0, + name: 'Eduardo', + } + + // create the store before changing + useStore(pinia) + pinia.state.value.main.name = 'Ed' + + expect(await renderToString(app)).toBe('') + }) + }) }) diff --git a/packages/pinia/src/store.ts b/packages/pinia/src/store.ts index d450d88c..66cd9eb5 100644 --- a/packages/pinia/src/store.ts +++ b/packages/pinia/src/store.ts @@ -410,7 +410,8 @@ function createSetupStore< ) ) as unknown as Store - // store the partial store now so the setup of stores can use each other + // store the partial store now so the setup of stores can instantiate each other before they are finished without + // creating infinite loops. pinia._s.set($id, store) // TODO: idea create skipSerialize that marks properties as non serializable and they are skipped @@ -430,7 +431,7 @@ function createSetupStore< // createOptionStore directly sets the state in pinia.state.value so we // can just skip that } else if (!buildState) { - // we must hydrate the state + // in setup stores we must hydrate the state and sync pinia state tree with the refs the user just created if (initialState) { if (isRef(prop)) { prop.value = initialState[key] @@ -636,7 +637,8 @@ function createSetupStore< } }) - if (initialState) { + // only apply hydrate to option stores with an initial state in pinia + if (initialState && buildState) { ;(options.hydrate || innerPatch)(store, initialState) }