-import { createPinia, defineStore, setActivePinia } from '../src'
-import { computed, nextTick, reactive, ref, watch } from 'vue'
+import { createPinia, defineStore, setActivePinia, skipHydrate } from '../src'
+import { computed, nextTick, reactive, ref, watch, customRef } from 'vue'
describe('State', () => {
beforeEach(() => {
expect(store.$state.stuff).toBe(15)
expect(store.double).toBe(30)
})
+
+ describe('custom refs', () => {
+ let spy!: jest.SpyInstance
+ function useCustomRef() {
+ let value = 0
+
+ return customRef((track, trigger) => {
+ spy = jest.fn(function (newValue: number) {
+ value = newValue
+ trigger()
+ })
+ return {
+ get() {
+ track()
+ return value
+ },
+ set: spy as any,
+ }
+ })
+ }
+
+ it('hydrates custom refs setup', async () => {
+ const pinia = createPinia()
+ pinia.state.value.main = { myCustom: 24 }
+
+ setActivePinia(pinia)
+
+ const useMainOptions = defineStore('main', () => ({
+ myCustom: skipHydrate(useCustomRef()),
+ }))
+
+ const main = useMainOptions()
+
+ // 0 because it skipped hydration
+ expect(main.myCustom).toBe(0)
+ expect(spy).toHaveBeenCalledTimes(0)
+ main.myCustom++
+ main.$state.myCustom++
+ main.$patch({ myCustom: 0 })
+ main.$patch((state) => {
+ state.myCustom++
+ })
+ expect(main.myCustom).toBe(1)
+ expect(spy).toHaveBeenCalledTimes(4)
+ })
+ })
})
export { createPinia } from './createPinia'
export type { Pinia, PiniaStorePlugin, PiniaPluginContext } from './rootStore'
-export { defineStore } from './store'
+export { defineStore, skipHydrate } from './store'
export type { StoreActions, StoreGetters, StoreState } from './store'
export type {
return target
}
+const skipHydrateSymbol = __DEV__ ? Symbol('pinia:skipHydration') : Symbol()
+
+export function skipHydrate<T = any>(obj: T): T {
+ return Object.defineProperty(obj, skipHydrateSymbol, {})
+}
+
+function shouldHydrate(obj: any) {
+ return !isPlainObject(obj) || !obj.hasOwnProperty(skipHydrateSymbol)
+}
+
const { assign } = Object
function isComputed<T>(value: ComputedRef<T> | unknown): value is ComputedRef<T>
// can just skip that
} else if (!buildState) {
// in setup stores we must hydrate the state and sync pinia state tree with the refs the user just created
- if (initialState) {
+ if (initialState && shouldHydrate(prop)) {
if (isRef(prop)) {
prop.value = initialState[key]
} else {