# SPA State Management - Vuex

Vuex is a **state management pattern + library** for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.

Vuex helps us deal with shared state management with the cost of more concepts and boilerplate. It's a trade-off between short term and long term productivity.

Vuex Stores are reactive. Each change in the store will update the components that use that part of the data.

![](/files/-MOHOGgKK71E1GUAyGjp)

* The **state**, the source of truth that drives our app;
* The **view**, a declarative mapping of the **state**;
* The **actions**, the possible ways the state could change in reaction to user inputs from the **view**.

### Mutations

The only way to actually change the State in a Vuex store is by committing a mutation. Vuex mutations are very similar to events: each mutation has a string **type** and a **handler**. The handler function is where we perform actual state modifications, and it will receive the state as the first argument.

### Actions

Actions are similar to mutations, the differences being that:

* Instead of mutating the state, actions commit mutations.
* Actions can contain arbitrary asynchronous operations.

### Getters

Vuex allows us to define "getters" in the store. You can think of them as computed properties for stores. Like computed properties, a getter's result is cached based on its dependencies, and will only re-evaluate when some of its dependencies have changed.

```javascript
export const store = new Vuex.Store({
  state: {
    counter: 0
  },
  //showing things, not mutating state
  getters: {
    tripleCounter: state => {
      return state.counter * 3
    }
  },
  //mutating the state
  //mutation are always synchronous
  mutations: {
    increment: (state, num) => {
      state.counter += num
    }
  },
  //commits the mutation, it's asynchronous
  actions: {
    //showing passed with payload (an object)
    asyncIncrement: ({ commit }, payload) => {
      setTimeout(() => {
        commit('increment', payload.by)
      }, payload.duration)
    }
  }
})
```

{% hint style="info" %}
**Why use Vuex?**

* **Simplified data flow:** Makes it easier to manage data in complex applications, especially when you have many components sharing and modifying the same data.
* **Predictable state changes:** Vuex enforces rules (mutations) to ensure that state changes happen in a predictable and trackable way, making debugging easier.
* **Reactivity:** Vuex stores are reactive, so when the state changes, components that use that data automatically update.
* **Improved organization:** Helps keep your data logic separate from your component logic, making your code cleaner and more maintainable.
  {% endhint %}

## Usage in components

### State:

`this.$store.state.nameOfThing`

### Getters:

`this.$store.getters.nameOfThing`

### Mutations:

`this.$store.commit('nameOfThing', payload)`

### Actions:

`this.$store.dispatch('nameOfThing', payload)`

```javascript
//...
computed: {
  count() { //this is cached until the dependecy is changed
    return this.$store.state.count
  },
  tripleCounter() {
    return this.$store.getters.tripleCounter
  }
},
methods: {
  increment() {
    this.$store.commit('increment', 2)
  },
  asyncIncrement() {
    this.$store.dispatch('asyncIncrement', 2) //2 is the payload
  }
}
//...
```

## Mapping the State

When a component needs to make use of multiple store state properties or getters, declaring all these computed properties can get repetitive and verbose. To deal with this we can make use of the `mapState` helper which generates computed getter functions for us.

```javascript
import { mapState } from 'vuex'

export default {
  //...
  computed: {
    ...mapState([
      //map this.count to this.$store.state.count
      'count', //destructuring
      'posts',
      'items'
    ])
  }
}
```

This is similar for `mapGetters`, `mapMutations`, `mapActions`.

## Full Docs

<https://vuex.vuejs.org/>

{% hint style="warning" %}
**Alternatives**

In Vue 3, Pinia is now the recommended state management solution. It offers a simpler and more intuitive API compared to Vuex, while still providing the core benefits of centralized state management.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mihai-gheorghe.gitbook.io/tic/vuejs-state-management.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
