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: v0.5.3~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=581bd08d978050fc5b9e8c6b32147cf3798b33cb;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 8013c008..f877bf42 100644 --- a/__tests__/store.patch.spec.ts +++ b/__tests__/store.patch.spec.ts @@ -1,4 +1,5 @@ -import { defineStore, setActivePinia, createPinia, Pinia } from '../src' +import { reactive, ref } from '@vue/composition-api' +import { createPinia, defineStore, setActivePinia, Pinia } from '../src' describe('store.patch', () => { let pinia: Pinia @@ -84,4 +85,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 e4f9927f..5e44cffc 100644 --- a/src/store.ts +++ b/src/store.ts @@ -11,6 +11,8 @@ import { provide, UnwrapRef, set, + isRef, + isReactive, } from '@vue/composition-api' 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-expect-error