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 particularly useful for global concerns like user authentication status, theme preferences, or, as demonstrated in the example, a shopping cart's contents shared across different UI sections.
Defining a Store: Alpine.store('storeName', { dataProperty: 'value', method() {} })
You define a global store using `Alpine.store()`. The first argument is a string name for your store, and the second is an object containing its data properties and methods. This object can also include JavaScript getters for computed properties.
// Example: Defining a simple user settings store
document.addEventListener('alpine:init', () => {
Alpine.store('settings', {
darkMode: false,
notificationsEnabled: true,
toggleDarkMode() {
this.darkMode = !this.darkMode;
},
get status() {
return `Dark Mode is ${this.darkMode ? 'ON' : 'OFF'}.`;
}
});
});
Accessing Store Data: $store.storeName.dataProperty
Within any Alpine component's HTML (`x-data`, `x-text`, `x-bind`, etc.) or JavaScript logic, you can access store data using the magic $store object followed by your store's name and the desired property.
<!-- Example: Accessing the darkMode property from the 'settings' store -->
<div :class="{ 'bg-gray-800 text-white': $store.settings.darkMode }">
Content
</div>
<p x-text="$store.settings.status"></p>
Calling Store Methods: $store.storeName.method()
Similarly, you can call methods defined in your store from any Alpine component, typically in event handlers like @click.
<!-- Example: Calling the toggleDarkMode method -->
<button @click="$store.settings.toggleDarkMode()">
Toggle Dark Mode
</button>
Defining a store after components try to access it: 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. This ensures Alpine is ready and your stores are registered before components render.
Modifying store data directly from many places without clear patterns: While you *can* directly modify store properties from components (e.g., $store.cart.items.push(...)), it's often better practice to define methods within the store itself to encapsulate state mutations (e.g., $store.cart.addItem(...)). This makes changes more predictable, centralized, and easier to debug. This is conceptually similar to using setter methods or service layer methods in backend Python frameworks to manage state changes rather than directly manipulating database fields from various parts of your application.
Overusing global state for data that is truly local to a component: 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/events, manage it with x-data. Global state is for truly global concerns shared across disparate parts of your application. Overuse can lead to complexity, much like overusing global variables in any programming language.
Items in cart:
Total Price: $
$
Total Items:
Total Price: $