--- 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 ``` **Correct:** ```vue ``` ## 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)