Alpine.js x-init Directive — Complete Guide with Examples
In this tutorial, you'll learn about the Alpine.js x-init directive. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
The Alpine.js x-init directive runs a JavaScript expression when a component is initialized, making it the ideal place for setup code, data fetching, and timer creation.
What You'll Learn
By the end of this tutorial, you'll use x-init to fetch API data, set up event listeners, run async code, initialize third-party libraries, and distinguish x-init from x-effect.
Why It Matters
Components often need startup code: loading initial data from an API, setting up a timer, measuring DOM elements, or initializing a chart library. x-init gives you a dedicated hook that runs once when the component is created.
Real-World Use
Durga Antivirus Pro's dashboard uses x-init in its scan status component to fetch the latest scan results from the API when the page loads, displaying them immediately without a manual refresh.
Where This Fits in Your Learning Path
flowchart LR
A["x-teleport Directive"] --> B["**x-init Directive**"]
B --> C["x-effect Directive"]
C --> D["Magics & Store"]
D --> E["Advanced Alpine Patterns"]
style B fill:#f97316,stroke:#c2410c,color:#fff
style A fill:#e5e7eb,stroke:#9ca3af,color:#374151
style E fill:#22c55e,stroke:#16a34a,color:#fff
What is x-init?
x-init is a directive that executes its expression once when the Alpine component is first created and added to the DOM. It runs after the component's data is initialized but before rendering.
Think of x-init like the ignition key of a car. When you turn the key, the engine starts, oil circulates, and the dashboard lights up. x-init is where you set everything in motion.
<div x-data="{ count: 0 }" x-init="console.log('Component created with count:', count)">
<p x-text="count"></p>
<button @click="count++">Increment</button>
</div>
Expected output: The browser console shows "Component created with count: 0" once when the page loads.
Fetching Data on Init
The most common use of x-init is to fetch initial data from an API.
<div x-data="{ user: null, loading: true }"
x-init="async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/users/1')
user = await res.json()
loading = false
}">
<p x-show="loading">Loading...</p>
<template x-if="!loading">
<div>
<h2 x-text="user.name"></h2>
<p x-text="user.email"></p>
</div>
</template>
</div>
Expected output: "Loading..." appears first. After the fetch completes, the user's name and email display.
Setting Up Timers and Intervals
x-init is the right place to start intervals or timers.
<div x-data="{ seconds: 0, timer: null }"
x-init="timer = setInterval(() => seconds++, 1000)">
<p>Elapsed: <span x-text="seconds"></span> seconds</p>
<button @click="clearInterval(timer); timer = null">Stop</button>
</div>
Expected output: The elapsed time increments every second. Clicking Stop clears the interval.
Using $refs in x-init
Access DOM elements via $refs during initialization, but use $nextTick if the element is conditionally rendered.
<div x-data
x-init="$nextTick(() => {
if ($refs.autoFocus) $refs.autoFocus.focus()
})">
<input x-ref="autoFocus" type="text" placeholder="I am focused on load">
</div>
Expected output: The input receives focus automatically when the page loads.
Async Functions in x-init
Use an async function expression for promises.
<div x-data="{ data: null, error: null }"
x-init="async function() {
try {
const res = await axios.get('https://jsonplaceholder.typicode.com/posts/1')
data = res.data
} catch (e) {
error = e.message
}
}()">
<p x-show="!data && !error">Loading...</p>
<p x-show="error" x-text="error"></p>
<pre x-show="data" x-text="JSON.stringify(data, null, 2)"></pre>
</div>
Expected output: Shows "Loading..." initially, then the fetched post data or an error message.
Common Mistakes
1. Using x-init instead of x-data for static values
<!-- Unnecessary: just set in x-data -->
<div x-data="{}" x-init="count = 0">
<!-- Better -->
<div x-data="{ count: 0 }">
2. Forgetting to clean up intervals and listeners
Intervals and event listeners created in x-init persist even if the component is removed. Always clean up in a mutation Observer or on destroy.
3. Using x-init for reactive side effects
If you need code that runs whenever specific data changes, use x-effect. x-init only runs once.
4. Not handling errors in async x-init
Unhandled promise rejections in x-init can cause silent failures. Always wrap async code in try/catch.
5. Assuming x-init runs after the DOM is fully rendered
x-init runs before Alpine renders the component. Use $nextTick if you need the DOM to be ready.
Practice Questions
When does x-init execute? It executes once when the Alpine component is initialized, after x-data is set up but before the first render.
How do you run async code in x-init? Use an async function expression: x-init="async () => { await fetch(...) }".
What is the difference between x-init and x-effect? x-init runs once on creation. x-effect runs whenever any reactive dependency changes.
How do you access a ref in x-init? Use $refs.name. If the ref is inside x-if, wrap in $nextTick.
Should you clean up intervals created in x-init? Yes. Intervals and listeners persist if the component is removed. Clean them up to prevent memory leaks.
Challenge
Build a countdown timer component that starts at 60 seconds and counts down to 0. Use x-init to set up the interval. Display minutes and seconds (MM:SS format). Stop when reaching 0.
FAQ
Mini Project
Build a real-time clock component that shows the current time and updates every second. Use x-init to start the interval and x-effect or a reactive property for the display.
<div x-data="{ time: '', day: '' }"
x-init="() => {
const update = () => {
const d = new Date()
time = d.toLocaleTimeString()
day = d.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' })
}
update()
setInterval(update, 1000)
}">
<div class="text-center p-8 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-lg">
<p class="text-4xl font-bold tracking-wider" x-text="time"></p>
<p class="text-lg text-gray-600 mt-2" x-text="day"></p>
</div>
</div>
What's Next
Continue with reactive effects:
| Tutorial | What You'll Learn |
|---|---|
| x-effect Directive | Run side effects when reactive state changes |
| Magics and Store | Global state and magic properties |
Related topics: JavaScript async/await, setInterval and setTimeout.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro