---
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)