From 581bd08d978050fc5b9e8c6b32147cf3798b33cb Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Mon, 7 Jun 2021 23:16:52 +0200 Subject: [PATCH] fix(patch): avoid merging reactive objects Fix #528 --- __tests__/store.patch.spec.ts | 54 ++++++++++++++++++++++++++++++++++- src/store.ts | 9 +++++- 2 files changed, 61 insertions(+), 2 deletions(-) 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 -- 2.47.3