expect(spy2).toHaveBeenCalledTimes(0)
s1.name = 'Edu'
-
expect(spy1).toHaveBeenCalledTimes(1)
expect(spy2).toHaveBeenCalledTimes(1)
expect(spy1).toHaveBeenCalledTimes(2)
expect(spy2).toHaveBeenCalledTimes(2)
+ s1.$patch((state) => {
+ state.name = 'other'
+ })
+ expect(spy1).toHaveBeenCalledTimes(3)
+ expect(spy2).toHaveBeenCalledTimes(3)
+
wrapper.unmount()
await nextTick()
s1.$patch({ name: 'b' })
- expect(spy1).toHaveBeenCalledTimes(2)
- expect(spy2).toHaveBeenCalledTimes(3)
+ expect(spy1).toHaveBeenCalledTimes(3)
+ expect(spy2).toHaveBeenCalledTimes(4)
+ s1.$patch((state) => {
+ state.name = 'c'
+ })
+ expect(spy1).toHaveBeenCalledTimes(3)
+ expect(spy2).toHaveBeenCalledTimes(5)
+ s1.name = 'd'
+ expect(spy1).toHaveBeenCalledTimes(3)
+ expect(spy2).toHaveBeenCalledTimes(6)
})
})
import { setActivePinia, piniaSymbol, Pinia, activePinia } from './rootStore'
import { IS_CLIENT } from './env'
import { patchObject } from './hmr'
-import { addSubscription, triggerSubscriptions } from './subscriptions'
+import { addSubscription, triggerSubscriptions, noop } from './subscriptions'
type _ArrayType<AT> = AT extends Array<infer T> ? T : never
return store as any
}
-const noop = () => {}
-
function createSetupStore<
Id extends string,
SS,
$patch,
$reset,
$subscribe(callback, options = {}) {
- const _removeSubscription = addSubscription(
+ const removeSubscription = addSubscription(
subscriptions,
callback,
- options.detached
+ options.detached,
+ () => stopWatcher()
)
const stopWatcher = scope.run(() =>
watch(
)
)!
- const removeSubscription = () => {
- stopWatcher()
- _removeSubscription()
- }
-
return removeSubscription
},
$dispose,
import { getCurrentInstance, onUnmounted } from 'vue-demi'
import { _Method } from './types'
+export const noop = () => {}
+
export function addSubscription<T extends _Method>(
subscriptions: T[],
callback: T,
- detached?: boolean
+ detached?: boolean,
+ onCleanup: () => void = noop
) {
subscriptions.push(callback)
const idx = subscriptions.indexOf(callback)
if (idx > -1) {
subscriptions.splice(idx, 1)
+ onCleanup()
}
}
/**
* Group multiple changes into one function. Useful when mutating objects like
* Sets or arrays and applying an object patch isn't practical, e.g. appending
- * to an array.
+ * to an array. The function passed to `$patch()` **must be synchronous**.
*
* @param stateMutator - function that mutates `state`, cannot be async
*/
- $patch<F extends (state: UnwrapRef<S>) => void>(
+ $patch<F extends (state: UnwrapRef<S>) => any>(
// this prevents the user from using `async` which isn't allowed
stateMutator: ReturnType<F> extends Promise<any> ? never : F
): void
const store = useStore()
+store.$patch({ counter: 2 })
+store.$patch((state) => {
+ expectType<number>(state.counter)
+})
+
expectType<number>(store.$state.counter)
expectType<number>(store.$state.double)
expectType<{ msg: string }>(store.aShallowRef)
expectType<{ msg: string }>(store.$state.aShallowRef)
+
+const onlyState = defineStore({
+ id: 'main',
+ state: () => ({
+ counter: 0,
+ }),
+})()
+
+onlyState.$patch({ counter: 2 })
+onlyState.$patch((state) => {
+ expectType<number>(state.counter)
+})