Returns a promise that resolves once any pending state changes have been applied to the DOM.
function tick(): Promise<void>
Returns
A promise that resolves after all pending state changes have been applied and the DOM has been updated
Examples
Waiting for DOM updates
<script>
import { tick } from 'svelte';
let count = $state(0);
async function increment() {
count++;
await tick();
// DOM has been updated
console.log('New count in DOM:', document.getElementById('count').textContent);
}
</script>
<p id="count">{count}</p>
<button onclick={increment}>Increment</button>
Focusing elements after conditional rendering
<script>
import { tick } from 'svelte';
let showInput = $state(false);
let inputElement;
async function reveal() {
showInput = true;
await tick();
inputElement?.focus();
}
</script>
<button onclick={reveal}>Show input</button>
{#if showInput}
<input bind:this={inputElement} type="text" />
{/if}
Measuring elements after update
<script>
import { tick } from 'svelte';
let items = $state([1, 2, 3]);
async function addItemAndMeasure() {
items.push(items.length + 1);
await tick();
const list = document.getElementById('list');
console.log('New list height:', list.offsetHeight);
}
</script>
<ul id="list">
{#each items as item}
<li>{item}</li>
{/each}
</ul>
<button onclick={addItemAndMeasure}>Add and measure</button>
Scrolling to new content
<script>
import { tick } from 'svelte';
let messages = $state([]);
let container;
async function addMessage(text) {
messages.push({ id: Date.now(), text });
await tick();
// Scroll to bottom after new message is rendered
container.scrollTop = container.scrollHeight;
}
</script>
<div bind:this={container} class="messages">
{#each messages as message (message.id)}
<div>{message.text}</div>
{/each}
</div>
<button onclick={() => addMessage('Hello!')}>Send message</button>
<style>
.messages {
height: 200px;
overflow-y: auto;
}
</style>
Sequential state updates
<script>
import { tick } from 'svelte';
let status = $state('idle');
async function runProcess() {
status = 'loading';
await tick();
console.log('Status UI updated to loading');
// Simulate async work
await fetch('/api/data');
status = 'success';
await tick();
console.log('Status UI updated to success');
}
</script>
<p>Status: {status}</p>
<button onclick={runProcess}>Run process</button>
Integration with third-party libraries
<script>
import { tick } from 'svelte';
import { initChart } from './chart-library';
let data = $state([10, 20, 30]);
let chartElement;
async function updateData(newData) {
data = newData;
await tick();
// DOM is updated, safe to initialize chart
initChart(chartElement, data);
}
</script>
<div bind:this={chartElement}></div>
<script>
import { tick } from 'svelte';
let email = $state('');
let errors = $state([]);
async function validateEmail() {
errors = [];
if (!email.includes('@')) {
errors.push('Invalid email');
}
await tick();
// Error messages are now in the DOM
if (errors.length > 0) {
document.querySelector('.error')?.scrollIntoView();
}
}
</script>
<input bind:value={email} onblur={validateEmail} />
{#each errors as error}
<p class="error">{error}</p>
{/each}
Use cases
- Focus management: Setting focus after elements are rendered
- DOM measurements: Getting element dimensions after updates
- Scroll positioning: Scrolling to new content after it’s added
- Third-party integrations: Ensuring DOM is ready for external libraries
- Testing: Waiting for updates in async tests
- Animations: Starting animations after state changes are reflected in the DOM
Behavior
tick() returns a promise that resolves after the next microtask
- Internally calls
flushSync() to ensure all pending updates are applied
- Multiple calls to
tick() can be chained with await
- Updates are batched automatically by Svelte for performance
Notes
tick() is asynchronous, unlike flushSync() which is synchronous
- Use
tick() when you don’t need immediate synchronous updates
- The promise resolves after Svelte’s internal update cycle completes
- This is the recommended approach for most cases where you need to wait for DOM updates
- Prior to Svelte 5, this was primarily used in Svelte 3/4 lifecycle methods