From: Eduardo San Martin Morote Date: Mon, 25 Oct 2021 14:37:40 +0000 (+0200) Subject: refactor(ssr): pass storeState instead of store to hydrate X-Git-Tag: @pinia/nuxt@0.1.0~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c85edacefc8c69a54e84afbcd577b8d1027b3065;p=thirdparty%2Fvuejs%2Fpinia.git refactor(ssr): pass storeState instead of store to hydrate BREAKING CHANGE: the `hydrate()` option for stores defined with the options api no longers passes the whole store instance. Instead, it passes the `storeState` so it can be directly modified. This is because it was currently necessary to hydrate the store by setting properties onto `store.$state`. This change makes it impossible to make the mistake anymore. ```diff defineStore('main', { state: () => ({ customRef: useLocalStorage('key', 0) }), - hydrate(store) { - store.$state.customRef = useLocalStorage('key', 0) + hydrate(storeState) { + storeState.customRef = useLocalStorage('key', 0) } }) ``` --- diff --git a/packages/pinia/__tests__/state.spec.ts b/packages/pinia/__tests__/state.spec.ts index a72140fb..f614f079 100644 --- a/packages/pinia/__tests__/state.spec.ts +++ b/packages/pinia/__tests__/state.spec.ts @@ -309,6 +309,46 @@ describe('State', () => { }) } + it('hydrates custom refs options', async () => { + const pinia = createPinia() + pinia.state.value.main = { myCustom: 24, other: 'ssr' } + + setActivePinia(pinia) + + const useMainOptions = defineStore('main', { + state: () => ({ myCustom: useCustomRef(), other: 'start' }), + hydrate(storeState, initialState) { + // @ts-expect-error: cannot set as a ref + storeState.myCustom = useCustomRef() + // Object.assign(store, initialState) + // const { myCustom, ...rest } = initialState + // Object.assign(store, rest) + }, + }) + + const main = useMainOptions() + + // skips the value from hydration + expect(main.myCustom).toBe(0) + expect(main.$state.myCustom).toBe(0) + expect(main.other).toBe('ssr') + expect(main.$state.other).toBe('ssr') + + expect(spy).toHaveBeenCalledTimes(0) + main.myCustom++ + main.$state.myCustom++ + main.$patch({ myCustom: 0 }) + main.$patch((state) => { + state.myCustom++ + }) + + expect(main.myCustom).toBe(1) + expect(main.$state.myCustom).toBe(1) + expect(main.other).toBe('ssr') + expect(main.$state.other).toBe('ssr') + expect(spy).toHaveBeenCalledTimes(4) + }) + it('hydrates custom refs setup', async () => { const pinia = createPinia() pinia.state.value.main = { myCustom: 24 } diff --git a/packages/pinia/src/store.ts b/packages/pinia/src/store.ts index d30301fc..950b3bfd 100644 --- a/packages/pinia/src/store.ts +++ b/packages/pinia/src/store.ts @@ -691,8 +691,15 @@ function createSetupStore< } // only apply hydrate to option stores with an initial state in pinia - if (initialState && buildState) { - ;(options.hydrate || innerPatch)(store, initialState) + if ( + initialState && + buildState && + (options as DefineStoreOptions).hydrate + ) { + ;(options as DefineStoreOptions).hydrate!( + store.$state, + initialState + ) } isListening = true diff --git a/packages/pinia/src/types.ts b/packages/pinia/src/types.ts index 4f7ef205..47376b99 100644 --- a/packages/pinia/src/types.ts +++ b/packages/pinia/src/types.ts @@ -654,7 +654,7 @@ export interface DefineStoreOptions< * Allows hydrating the store during SSR when there is an available state in * pinia.state. * - * @param store - the store + * @param storeState - the current state in the store * @param initialState - initialState */ hydrate?(storeState: UnwrapRef, initialState: UnwrapRef): void