Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

x-init and x-effect

Sometimes code has to run on its own rather than on an event: when a component appears on the page, or every time its data changes. The first case is handled by x-init, the second by x-effect.

x-init

The expression in x-init runs once, when Alpine starts the element:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{ today: '' }" x-init="today = new Date().toLocaleDateString('en-US')">
  <p>Tasks for <span x-text="today"></span></p>
</div>

The list heading shows today's date. Date formatting was covered in the "Formatting with Intl" lesson of the tutorial.

The init() method

If the component's data has an init() method, Alpine calls it by itself when the component starts. This reads better than a long x-init when there is a lot of code:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{
  tasks: [],
  init() {
    this.tasks = ['Buy milk', 'Call Oleg'];
    console.log('Component started, tasks:', this.tasks.length);
  }
}">
  <p x-text="tasks.join(', ')"></p>
</div>

The page shows two tasks, and the console under the example prints "Component started, tasks: 2". Later, init() will load data from a server.

x-effect

The expression in x-effect runs immediately and then again every time the data it reads changes. Alpine tracks which properties are used by itself:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{ tasks: ['Buy milk'] }" x-effect="console.log('Tasks:', tasks.length)">
  <button @click="tasks.push('New task')">Add</button>
</div>

The console prints "Tasks: 1" right away, and each click prints the new number. If the expression did not read tasks, it would run only once.

Which to choose

TaskDirective
Prepare data on startx-init or the init() method
Load data from a serverThe init() method
Repeat an action on every data changex-effect
Watch one specific property$watch, covered in a later lesson

Common mistake

Expecting x-init to run again when data changes:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{ tasks: ['Buy milk'] }" x-init="console.log('Tasks:', tasks.length)">
  <button @click="tasks.push('New task')">Add</button>
</div>

The console has one line, "Tasks: 1", and clicks add nothing to it: x-init runs only on start. When an action has to follow the data, use x-effect.

Thanks for reading!

Donate to the site — we work hard for you.