Description: Alpine.store allows you to define and access shared, reactive data or state that is accessible from any Alpine component on the page. This is incredibly useful for managing global concerns like user authentication status, application-wide settings (e.g., theme), or a shopping cart's contents.
Defining a Store: You define a store using Alpine.store('storeName', { ... }). This is typically done within a <script> tag, inside the alpine:init event listener.
// Inside document.addEventListener('alpine:init', () => { ... });
Alpine.store('cart', {
items: [],
total: 0,
addItem(item) {
this.items.push(item);
this.calculateTotal();
},
calculateTotal() {
this.total = this.items.reduce((sum, item) => sum + item.price, 0);
}
});
The object passed as the second argument contains the store's reactive data properties (like items and total) and methods (like addItem and calculateTotal) that can modify this data.
Accessing Store Data: In your Alpine components (within x-data, x-text, x-bind, etc.), you can access store data using the magic $store object: $store.storeName.dataProperty.
<div x-data>
Number of items in cart: <span x-text="$store.cart.items.length"></span>
Cart Total: <span x-text="$store.cart.total"></span>
</div>
Calling Store Methods: Similarly, you can call methods defined in your store: $store.storeName.method().
<div x-data>
<button @click="$store.cart.addItem({ name: 'New Product', price: 10 })">
Add Product
</button>
</div>
Alpine.store() must be defined before any Alpine components that rely on it are initialized. The best practice is to define all your stores within the document.addEventListener('alpine:init', () => { ... }); callback, typically in a script tag placed just before the closing </body> tag, or right after the AlpineJS script include if you prefer it in the <head>.
While you can directly modify store properties from components (e.g., $store.cart.items.push(...) or $store.appSettings.theme = 'dark'), it's generally better practice to define methods within the store itself to encapsulate state mutations (e.g., $store.cart.addItem(...), $store.appSettings.setTheme('dark')). This makes state changes more predictable, centralized, and easier to debug, much like using setters, service methods, or reducers in other state management patterns or backend architectures.
Don't put everything in Alpine.store. If data is only relevant to a single component or a small group of closely related components that can communicate via props and events, manage it locally with x-data. Global state is powerful but should be reserved for data that genuinely needs to be shared across disparate parts of your application. Overuse can lead to complexity, similar to overusing global variables in Python.
Loading user preferences...
Current theme:
This component also observes the theme: .
The page background and text colors also change based on the theme.
Global theme according to me: .
Username:
Initial Preferred Theme (from mock server):