From 9ae10167ba5b3b41d8b0f1f977fdad96208b2669 Mon Sep 17 00:00:00 2001 From: Caleb Hearon Date: Tue, 25 Jan 2022 12:43:12 -0500 Subject: [PATCH 1/2] fix(shallowReactive): don't trigger watchers for oldVal === newVal --- src/reactivity/reactive.ts | 3 ++- src/reactivity/ref.ts | 4 +++- test/v3/reactivity/ref.spec.ts | 20 +++++++++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/reactivity/reactive.ts b/src/reactivity/reactive.ts index 386cb299..6775055e 100644 --- a/src/reactivity/reactive.ts +++ b/src/reactivity/reactive.ts @@ -213,7 +213,8 @@ export function shallowReactive(obj: any) { return value }, set: function setterHandler(newVal: any) { - if (getter && !setter) return + const value = getter ? getter.call(obj) : val + if (newVal === value || (getter && !setter)) return if (setter) { setter.call(obj, newVal) } else { diff --git a/src/reactivity/ref.ts b/src/reactivity/ref.ts index 044a63df..3da768ab 100644 --- a/src/reactivity/ref.ts +++ b/src/reactivity/ref.ts @@ -184,7 +184,9 @@ export function shallowRef(raw?: unknown) { export function triggerRef(value: any) { if (!isRef(value)) return - value.value = value.value + const v = value.value + value.value = !v + value.value = v } export function proxyRefs( diff --git a/test/v3/reactivity/ref.spec.ts b/test/v3/reactivity/ref.spec.ts index b4f9c958..1443f922 100644 --- a/test/v3/reactivity/ref.spec.ts +++ b/test/v3/reactivity/ref.spec.ts @@ -250,11 +250,29 @@ describe('reactivity/ref', () => { expect(dummy).toBe(1) // should not trigger yet // force trigger - // sref.value = sref.value; triggerRef(sref) expect(dummy).toBe(2) }) + test('shallowRef noop when assignment is the same', () => { + const sref = shallowRef(1) + let calls = 0 + watchEffect( + () => { + sref.value + calls++ + }, + { flush: 'sync' } + ) + expect(calls).toBe(1) + + sref.value = 2 + expect(calls).toBe(2) + + sref.value = 2 + expect(calls).toBe(2) + }) + test('isRef', () => { expect(isRef(ref(1))).toBe(true) expect(isRef(computed(() => 1))).toBe(true) From 7d56c628baf78e9f50f5f59e7713d1b2093b8ca8 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Thu, 27 Jan 2022 15:47:52 +0800 Subject: [PATCH 2/2] chore: update --- src/reactivity/force.ts | 9 +++++++++ src/reactivity/reactive.ts | 4 +++- src/reactivity/ref.ts | 7 ++++--- 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 src/reactivity/force.ts diff --git a/src/reactivity/force.ts b/src/reactivity/force.ts new file mode 100644 index 00000000..727e0f5f --- /dev/null +++ b/src/reactivity/force.ts @@ -0,0 +1,9 @@ +let _isForceTrigger = false + +export function isForceTrigger() { + return _isForceTrigger +} + +export function setForceTrigger(v: boolean) { + _isForceTrigger = v +} diff --git a/src/reactivity/reactive.ts b/src/reactivity/reactive.ts index 6775055e..e91f2704 100644 --- a/src/reactivity/reactive.ts +++ b/src/reactivity/reactive.ts @@ -14,6 +14,7 @@ import { isComponentInstance, defineComponentInstance } from '../utils/helper' import { RefKey } from '../utils/symbols' import { isRef, UnwrapRef } from './ref' import { rawSet, accessModifiedSet } from '../utils/sets' +import { isForceTrigger } from './force' export function isRaw(obj: any): boolean { return Boolean( @@ -213,8 +214,9 @@ export function shallowReactive(obj: any) { return value }, set: function setterHandler(newVal: any) { + if (getter && !setter) return const value = getter ? getter.call(obj) : val - if (newVal === value || (getter && !setter)) return + if (!isForceTrigger() && value === newVal) return if (setter) { setter.call(obj, newVal) } else { diff --git a/src/reactivity/ref.ts b/src/reactivity/ref.ts index 3da768ab..4da6a55f 100644 --- a/src/reactivity/ref.ts +++ b/src/reactivity/ref.ts @@ -3,6 +3,7 @@ import { proxy, isPlainObject, warn, def } from '../utils' import { reactive, isReactive, shallowReactive } from './reactive' import { readonlySet } from '../utils/sets' import { set } from './set' +import { setForceTrigger } from './force' declare const _refBrand: unique symbol export interface Ref { @@ -184,9 +185,9 @@ export function shallowRef(raw?: unknown) { export function triggerRef(value: any) { if (!isRef(value)) return - const v = value.value - value.value = !v - value.value = v + setForceTrigger(true) + value.value = value.value + setForceTrigger(false) } export function proxyRefs(