Skip to content

Commit

Permalink
feat(ssr): add skipHydrate to skip hydration on specific refs
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Oct 25, 2021
1 parent 37d07fb commit 55deedb
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
50 changes: 48 additions & 2 deletions packages/pinia/__tests__/state.spec.ts
@@ -1,5 +1,5 @@
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(() => {
Expand Down Expand Up @@ -288,4 +288,50 @@ describe('State', () => {
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)
})
})
})
2 changes: 1 addition & 1 deletion packages/pinia/src/index.ts
Expand Up @@ -5,7 +5,7 @@ export { setActivePinia, getActivePinia } from './rootStore'
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 {
Expand Down
12 changes: 11 additions & 1 deletion packages/pinia/src/store.ts
Expand Up @@ -73,6 +73,16 @@ function innerPatch<T extends StateTree>(
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>
Expand Down Expand Up @@ -445,7 +455,7 @@ function createSetupStore<
// 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 {
Expand Down

0 comments on commit 55deedb

Please sign in to comment.