From: Eduardo San Martin Morote Date: Thu, 1 Apr 2021 14:37:20 +0000 (+0200) Subject: feat: allow passing a function to $patch X-Git-Tag: v0.2.5~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3be1c81eabd726780ce6b5d1919a2f60d72b3e84;p=thirdparty%2Fvuejs%2Fpinia.git feat: allow passing a function to $patch --- diff --git a/__tests__/store.patch.spec.ts b/__tests__/store.patch.spec.ts index ffe2e2bb..2325826a 100644 --- a/__tests__/store.patch.spec.ts +++ b/__tests__/store.patch.spec.ts @@ -17,6 +17,7 @@ describe('store.patch', () => { foo: 'foo', a: { b: 'string' }, }, + list: [] as number[], }), })() } @@ -30,6 +31,24 @@ describe('store.patch', () => { foo: 'foo', a: { b: 'string' }, }, + list: [], + }) + }) + + it('patches using a function', () => { + const store = useStore() + store.$patch((state) => { + expect(state).toBe(store.$state) + state.a = !state.a + state.list.push(1) + }) + expect(store.$state).toEqual({ + a: false, + nested: { + foo: 'foo', + a: { b: 'string' }, + }, + list: [1], }) }) @@ -42,6 +61,7 @@ describe('store.patch', () => { foo: 'bar', a: { b: 'string' }, }, + list: [], }) store.$patch({ nested: { a: { b: 'hello' } } }) expect(store.$state).toEqual({ @@ -50,6 +70,7 @@ describe('store.patch', () => { foo: 'bar', a: { b: 'hello' }, }, + list: [], }) }) @@ -62,6 +83,7 @@ describe('store.patch', () => { foo: 'hello', a: { b: 'string' }, }, + list: [], }) }) }) diff --git a/src/store.ts b/src/store.ts index 61c4aeef..8eff1e26 100644 --- a/src/store.ts +++ b/src/store.ts @@ -96,14 +96,27 @@ function initStore( let isListening = true let subscriptions: SubscriptionCallback[] = [] - function $patch(partialState: DeepPartial): void { + function $patch(stateMutation: (state: S) => void): void + function $patch(partialState: DeepPartial): void + function $patch( + partialStateOrMutator: DeepPartial | ((state: S) => void) + ): void { + let partialState: DeepPartial = {} + let type: string isListening = false - innerPatch(pinia.state.value[$id], partialState) + if (typeof partialStateOrMutator === 'function') { + partialStateOrMutator(pinia.state.value[$id]) + type = '🧩 patch' + } else { + innerPatch(pinia.state.value[$id], partialStateOrMutator) + partialState = partialStateOrMutator + type = '⤵️ patch' + } isListening = true // because we paused the watcher, we need to manually call the subscriptions subscriptions.forEach((callback) => { callback( - { storeName: $id, type: '⤵️ patch', payload: partialState }, + { storeName: $id, type, payload: partialState }, pinia.state.value[$id] ) }) diff --git a/src/types.ts b/src/types.ts index b707f193..3c774617 100644 --- a/src/types.ts +++ b/src/types.ts @@ -56,6 +56,15 @@ export interface StoreWithState { */ $patch(partialState: DeepPartial): void + /** + * 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. + * + * @param stateMutator - function that mutates `state` + */ + $patch(stateMutator: (state: S) => void): void + /** * Resets the store to its initial state by removing all subscriptions and * building a new state object