Skip to content

Commit 2a88e71

Browse files
chearonantfu
andauthored
fix(shallowReactive): don't trigger watchers for oldVal === newVal (#894)
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
1 parent 7243ffa commit 2a88e71

File tree

4 files changed

+34
-1
lines changed

4 files changed

+34
-1
lines changed

src/reactivity/force.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
let _isForceTrigger = false
2+
3+
export function isForceTrigger() {
4+
return _isForceTrigger
5+
}
6+
7+
export function setForceTrigger(v: boolean) {
8+
_isForceTrigger = v
9+
}

src/reactivity/reactive.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { isComponentInstance, defineComponentInstance } from '../utils/helper'
1414
import { RefKey } from '../utils/symbols'
1515
import { isRef, UnwrapRef } from './ref'
1616
import { rawSet, accessModifiedSet } from '../utils/sets'
17+
import { isForceTrigger } from './force'
1718

1819
export function isRaw(obj: any): boolean {
1920
return Boolean(
@@ -213,6 +214,8 @@ export function shallowReactive(obj: any) {
213214
},
214215
set: function setterHandler(newVal: any) {
215216
if (getter && !setter) return
217+
const value = getter ? getter.call(obj) : val
218+
if (!isForceTrigger() && value === newVal) return
216219
if (setter) {
217220
setter.call(obj, newVal)
218221
} else {

src/reactivity/ref.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { proxy, isPlainObject, warn, def } from '../utils'
33
import { reactive, isReactive, shallowReactive } from './reactive'
44
import { readonlySet } from '../utils/sets'
55
import { set } from './set'
6+
import { setForceTrigger } from './force'
67

78
declare const _refBrand: unique symbol
89
export interface Ref<T = any> {
@@ -184,7 +185,9 @@ export function shallowRef(raw?: unknown) {
184185
export function triggerRef(value: any) {
185186
if (!isRef(value)) return
186187

188+
setForceTrigger(true)
187189
value.value = value.value
190+
setForceTrigger(false)
188191
}
189192

190193
export function proxyRefs<T extends object>(

test/v3/reactivity/ref.spec.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,29 @@ describe('reactivity/ref', () => {
250250
expect(dummy).toBe(1) // should not trigger yet
251251

252252
// force trigger
253-
// sref.value = sref.value;
254253
triggerRef(sref)
255254
expect(dummy).toBe(2)
256255
})
257256

257+
test('shallowRef noop when assignment is the same', () => {
258+
const sref = shallowRef(1)
259+
let calls = 0
260+
watchEffect(
261+
() => {
262+
sref.value
263+
calls++
264+
},
265+
{ flush: 'sync' }
266+
)
267+
expect(calls).toBe(1)
268+
269+
sref.value = 2
270+
expect(calls).toBe(2)
271+
272+
sref.value = 2
273+
expect(calls).toBe(2)
274+
})
275+
258276
test('isRef', () => {
259277
expect(isRef(ref(1))).toBe(true)
260278
expect(isRef(computed(() => 1))).toBe(true)

0 commit comments

Comments
 (0)