Skip to content

Alpine.js x-init Directive — Complete Guide with Examples

DodaTech Updated 2026-06-28 5 min read

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

  1. 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.

  2. How do you run async code in x-init? Use an async function expression: x-init="async () => { await fetch(...) }".

  3. What is the difference between x-init and x-effect? x-init runs once on creation. x-effect runs whenever any reactive dependency changes.

  4. How do you access a ref in x-init? Use $refs.name. If the ref is inside x-if, wrap in $nextTick.

  5. 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

Does x-init run again if x-if recreates the component?

Yes. Each time x-if evaluates to true and creates the component, x-init runs again. Use x-show if you want x-init to run only once.

Can I use multiple x-init directives on the same element?

No. Only one x-init per element. Combine multiple statements with semicolons or use a function.

Is x-init the right place for API calls?

Yes. x-init is the standard place for fetching initial data. The async function pattern makes it clean and readable.

What is the 'this' context inside x-init?

'this' refers to the component's data object. You can access all reactive properties via this.propertyName.

Can I use $watch inside x-init?

Yes. $watch can be called inside x-init to set up watchers when the component initializes.


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