---
title: Use flush post When Accessing Updated DOM in Watchers
impact: MEDIUM
impactDescription: Default watcher timing runs before DOM updates, causing stale DOM reads
type: capability
tags: [vue3, watch, watchers, flush, DOM, timing, post]
---
# Use flush: 'post' When Accessing Updated DOM in Watchers
**Impact: MEDIUM** - By default, watcher callbacks run before the component's DOM is updated. If you access the DOM in a watcher callback, you'll see the pre-update state. Use `flush: 'post'` or `watchPostEffect` when you need to access the updated DOM.
## Task Checklist
- [ ] Use `{ flush: 'post' }` when reading DOM after reactive state changes
- [ ] Use `watchPostEffect()` as a shorthand for `watchEffect` with flush: 'post'
- [ ] Avoid `{ flush: 'sync' }` unless absolutely necessary (performance impact)
- [ ] Remember default timing is ideal for most non-DOM operations
**Incorrect:**
```vue
{{ count }}
```
**Correct:**
```vue
{{ count }}
```
## Flush Timing Options
```javascript
import { watch, watchEffect, watchPostEffect, watchSyncEffect } from 'vue'
// Default: 'pre' - runs before component DOM update
watch(source, callback) // Same as { flush: 'pre' }
// Post: runs after component DOM update
watch(source, callback, { flush: 'post' })
watchPostEffect(callback) // Shorthand
// Sync: runs immediately when reactive value changes
// USE WITH CAUTION - no batching, fires on every mutation
watch(source, callback, { flush: 'sync' })
watchSyncEffect(callback) // Shorthand
```
## When to Use Each Flush Timing
| Timing | Use Case |
|--------|----------|
| `'pre'` (default) | Logic that doesn't need DOM access |
| `'post'` | Reading or measuring updated DOM |
| `'sync'` | Debug logging, simple boolean flags only |
## Sync Watcher Warning
```javascript
import { ref, watch } from 'vue'
const items = ref([1, 2, 3])
// DANGEROUS: Fires for EVERY array mutation
watch(
items,
() => {
console.log('Changed!') // Called 3 times for push, push, push
},
{ flush: 'sync' }
)
// This triggers the watcher 3 times synchronously
items.value.push(4)
items.value.push(5)
items.value.push(6)
// Better: Use default flush which batches updates
watch(items, () => {
console.log('Changed!') // Called once after all mutations
}, { deep: true })
```
## Practical Example: Auto-scroll
```vue
```
## Reference
- [Vue.js Watchers - Callback Flush Timing](https://vuejs.org/guide/essentials/watchers.html#callback-flush-timing)