Skip to content

Commit f7f1e77

Browse files
authored
fix(watchEffect): prevent recursive calls when using flush:sync (#389)
* fix(watchEffect): prevent recursive calls when using `flush:sync` * chore: better comment
1 parent 233dafa commit f7f1e77

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

src/apis/watch.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,19 @@ function createWatcher(
230230

231231
// effect watch
232232
if (cb === null) {
233-
const getter = () => (source as WatchEffect)(registerCleanup)
233+
let running = false
234+
const getter = () => {
235+
// preventing the watch callback being call in the same execution
236+
if (running) {
237+
return
238+
}
239+
try {
240+
running = true
241+
;(source as WatchEffect)(registerCleanup)
242+
} finally {
243+
running = false
244+
}
245+
}
234246
const watcher = createVueWatcher(vm, getter, noopFn, {
235247
deep: options.deep || false,
236248
sync: isSync,

test/v3/runtime-core/apiWatch.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,4 +514,22 @@ describe('api: watch', () => {
514514
// expect(spy).toHaveBeenCalledTimes(1);
515515
// expect(warnSpy).toHaveBeenCalledWith(`"deep" option is only respected`);
516516
// });
517+
518+
519+
// #388
520+
it('should not call the callback multiple times', () => {
521+
const data = ref([1, 1, 1, 1, 1])
522+
const data2 = ref<number[]>([])
523+
524+
watchEffect(
525+
() => {
526+
data2.value = data.value.slice(1, 2)
527+
},
528+
{
529+
flush: 'sync',
530+
}
531+
)
532+
533+
expect(data2.value).toMatchObject([1])
534+
})
517535
})

0 commit comments

Comments
 (0)