For applications whose state spans many components, Vue's official state management library is Pinia, which replaced Vuex as the recommended solution. Pinia is intentionally simple: there are no separate mutations, every store supports full TypeScript inference, and stores can be written in either the Options style or the Composition style. Each store is independent and modular, and Pinia integrates with the Vue DevTools for time-travel debugging and state inspection.
A store is defined with defineStore() from the pinia package. In the Options style, you supply an object with a state function returning the initial data, a getters object for derived values, and an actions object for methods that contain business logic or async work. In the Composition style, the second argument is a setup function that uses ref, computed, and regular functions and returns whatever should be exposed. This dual syntax means you can pick the style that best matches the rest of your component code, and stores can even be split across multiple files when they grow large.
Pinia getters are equivalent to computed properties for stores: they are cached and only recalculate when their reactive dependencies change. They can also reference other getters, including via this in the Options style. Pinia actions, unlike the old Vuex mutations, freely support async operations, can call other actions, and are not strictly required to be synchronous. Once a store is defined, you consume it in any component by calling the returned useStore() function, after which the store's state, getters, and actions are available as direct properties on the result.