From: Eduardo San Martin Morote Date: Mon, 7 Jun 2021 21:16:52 +0000 (+0200) Subject: fix(patch): avoid merging reactive objects X-Git-Tag: v2.0.0-beta.3~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a6a75e891d3fc4a7ec2c5dea3ac8081cf460c4d2;p=thirdparty%2Fvuejs%2Fpinia.git fix(patch): avoid merging reactive objects Fix #528 --- diff --git a/__tests__/store.patch.spec.ts b/__tests__/store.patch.spec.ts index 6b6c1f8e..9156f543 100644 --- a/__tests__/store.patch.spec.ts +++ b/__tests__/store.patch.spec.ts @@ -1,3 +1,4 @@ +import { reactive, ref } from 'vue' import { createPinia, defineStore, setActivePinia } from '../src' describe('store.$patch', () => { @@ -81,4 +82,55 @@ describe('store.$patch', () => { list: [], }) }) + + describe('skipping nested objects', () => { + const useStore = () => { + // create a new store + setActivePinia(createPinia()) + return defineStore({ + id: 'main', + state: () => ({ + arr: [] as any[], + item: { a: 0, b: 0 } as null | { a: number; b?: number }, + }), + })() + } + + it('ref', () => { + const store = useStore() + const item = ref({ a: 1, b: 1 }) + const oldItem = store.item + // @ts-expect-error: because it's a ref + store.$patch({ item }) + expect(oldItem).toEqual({ a: 0, b: 0 }) + expect(store.item).toEqual({ a: 1, b: 1 }) + }) + + it('nested ref', () => { + const store = useStore() + const item = ref({ nested: { a: 1, b: 1 } }) + const oldItem = store.item + store.$patch({ item: item.value.nested }) + expect(oldItem).toEqual({ a: 0, b: 0 }) + expect(store.item).toEqual({ a: 1, b: 1 }) + }) + + it('reactive', () => { + const store = useStore() + const item = reactive({ a: 1, b: 1 }) + const oldItem = store.item + store.$patch({ item }) + expect(oldItem).toEqual({ a: 0, b: 0 }) + expect(store.item).toEqual({ a: 1, b: 1 }) + }) + + it('from store', () => { + const store = useStore() + store.arr.push({ a: 1, b: 1 }) + const oldItem = store.item + store.$patch({ item: store.arr[0] }) + expect(oldItem).toEqual({ a: 0, b: 0 }) + expect(store.item).toEqual({ a: 1, b: 1 }) + }) + }) }) diff --git a/src/store.ts b/src/store.ts index 105d1121..0a7964c2 100644 --- a/src/store.ts +++ b/src/store.ts @@ -12,6 +12,8 @@ import { WatchOptions, UnwrapRef, markRaw, + isRef, + isReactive, } from 'vue' import { StateTree, @@ -50,7 +52,12 @@ function innerPatch( for (const key in patchToApply) { const subPatch = patchToApply[key] const targetValue = target[key] - if (isPlainObject(targetValue) && isPlainObject(subPatch)) { + if ( + isPlainObject(targetValue) && + isPlainObject(subPatch) && + !isRef(subPatch) && + !isReactive(subPatch) + ) { target[key] = innerPatch(targetValue, subPatch) } else { // @ts-ignore