Skip to content

Commit 5742a0b

Browse files
authored
fix(runtime-core/watch): trigger watcher with undefined as initial value (#687)
Fix #683
1 parent 3ddb441 commit 5742a0b

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

packages/runtime-core/__tests__/apiWatch.spec.ts

+27
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,33 @@ describe('api: watch', () => {
2727
expect(dummy).toBe(1)
2828
})
2929

30+
it('triggers when initial value is null', async () => {
31+
const state = ref(null)
32+
const spy = jest.fn()
33+
watch(() => state.value, spy)
34+
await nextTick()
35+
expect(spy).toHaveBeenCalled()
36+
})
37+
38+
it('triggers when initial value is undefined', async () => {
39+
const state = ref()
40+
const spy = jest.fn()
41+
watch(() => state.value, spy)
42+
await nextTick()
43+
expect(spy).toHaveBeenCalled()
44+
state.value = 3
45+
await nextTick()
46+
expect(spy).toHaveBeenCalledTimes(2)
47+
// testing if undefined can trigger the watcher
48+
state.value = undefined
49+
await nextTick()
50+
expect(spy).toHaveBeenCalledTimes(3)
51+
// it shouldn't trigger if the same value is set
52+
state.value = undefined
53+
await nextTick()
54+
expect(spy).toHaveBeenCalledTimes(3)
55+
})
56+
3057
it('watching single source: getter', async () => {
3158
const state = reactive({ count: 0 })
3259
let dummy

packages/runtime-core/src/apiWatch.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ export type StopHandle = () => void
6161

6262
const invoke = (fn: Function) => fn()
6363

64+
// initial value for watchers to trigger on undefined initial values
65+
const INITIAL_WATCHER_VALUE = {}
66+
6467
// overload #1: simple effect
6568
export function watch(effect: WatchEffect, options?: WatchOptions): StopHandle
6669

@@ -153,7 +156,7 @@ function doWatch(
153156
}
154157
}
155158

156-
let oldValue = isArray(source) ? [] : undefined
159+
let oldValue = isArray(source) ? [] : INITIAL_WATCHER_VALUE
157160
const applyCb = cb
158161
? () => {
159162
if (instance && instance.isUnmounted) {
@@ -167,7 +170,8 @@ function doWatch(
167170
}
168171
callWithAsyncErrorHandling(cb, instance, ErrorCodes.WATCH_CALLBACK, [
169172
newValue,
170-
oldValue,
173+
// pass undefined as the old value when it's changed for the first time
174+
oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue,
171175
registerCleanup
172176
])
173177
oldValue = newValue

0 commit comments

Comments
 (0)