In this section, we will learn how to integrate Vuex into Vue components. 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.

Key Concepts

  1. State: The single source of truth that stores the data.
  2. Getters: Functions to get derived state.
  3. Mutations: Synchronous functions to change the state.
  4. Actions: Asynchronous functions that commit mutations.
  5. Modules: Divide the store into modules for better organization.

Steps to Use Vuex in Components

  1. Accessing State: Use this.$store.state to access the state.
  2. Using Getters: Use this.$store.getters to access getters.
  3. Committing Mutations: Use this.$store.commit to commit mutations.
  4. Dispatching Actions: Use this.$store.dispatch to dispatch actions.

Practical Example

Let's create a simple Vuex store and integrate it into a Vue component.

Step 1: Setting Up Vuex Store

First, we need to set up a Vuex store. Create a file named store.js:

// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    count: 0
  },
  getters: {
    doubleCount: state => state.count * 2
  },
  mutations: {
    increment(state) {
      state.count++;
    },
    decrement(state) {
      state.count--;
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment');
      }, 1000);
    }
  }
});

Step 2: Integrating Vuex Store into Vue Application

Next, integrate the Vuex store into your Vue application. Modify your main.js:

// main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store';

Vue.config.productionTip = false;

new Vue({
  store,
  render: h => h(App),
}).$mount('#app');

Step 3: Using Vuex in a Component

Now, let's create a component that uses the Vuex store. Create a file named Counter.vue:

<!-- Counter.vue -->
<template>
  <div>
    <p>Count: {{ count }}</p>
    <p>Double Count: {{ doubleCount }}</p>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
    <button @click="incrementAsync">Increment Async</button>
  </div>
</template>

<script>
export default {
  computed: {
    count() {
      return this.$store.state.count;
    },
    doubleCount() {
      return this.$store.getters.doubleCount;
    }
  },
  methods: {
    increment() {
      this.$store.commit('increment');
    },
    decrement() {
      this.$store.commit('decrement');
    },
    incrementAsync() {
      this.$store.dispatch('incrementAsync');
    }
  }
};
</script>

Explanation

  • Computed Properties: We use computed properties to map the state and getters to the component.
    computed: {
      count() {
        return this.$store.state.count;
      },
      doubleCount() {
        return this.$store.getters.doubleCount;
      }
    }
    
  • Methods: We define methods to commit mutations and dispatch actions.
    methods: {
      increment() {
        this.$store.commit('increment');
      },
      decrement() {
        this.$store.commit('decrement');
      },
      incrementAsync() {
        this.$store.dispatch('incrementAsync');
      }
    }
    

Step 4: Using the Component

Finally, use the Counter component in your App.vue:

<!-- App.vue -->
<template>
  <div id="app">
    <Counter />
  </div>
</template>

<script>
import Counter from './components/Counter.vue';

export default {
  components: {
    Counter
  }
};
</script>

Practical Exercises

Exercise 1: Add a Reset Button

Task: Add a button to the Counter component that resets the count to zero.

Solution:

  1. Add a mutation to reset the count:

    mutations: {
      reset(state) {
        state.count = 0;
      }
    }
    
  2. Add a method in the Counter component to commit the reset mutation:

    methods: {
      reset() {
        this.$store.commit('reset');
      }
    }
    
  3. Add a button in the template:

    <button @click="reset">Reset</button>
    

Exercise 2: Add a Decrement Async Button

Task: Add a button to the Counter component that decrements the count asynchronously.

Solution:

  1. Add an action to decrement the count asynchronously:

    actions: {
      decrementAsync({ commit }) {
        setTimeout(() => {
          commit('decrement');
        }, 1000);
      }
    }
    
  2. Add a method in the Counter component to dispatch the decrementAsync action:

    methods: {
      decrementAsync() {
        this.$store.dispatch('decrementAsync');
      }
    }
    
  3. Add a button in the template:

    <button @click="decrementAsync">Decrement Async</button>
    

Common Mistakes and Tips

  • Direct State Mutation: Avoid directly mutating the state outside of mutations. Always use commit to change the state.
  • Using Getters for Computed Properties: Use getters for any derived state to keep your components clean and focused on presentation.
  • Asynchronous Operations in Mutations: Do not perform asynchronous operations in mutations. Use actions for any async logic and then commit mutations.

Conclusion

In this section, we learned how to integrate Vuex into Vue components. We covered accessing state, using getters, committing mutations, and dispatching actions. We also provided practical examples and exercises to reinforce the concepts. In the next module, we will dive deeper into advanced Vuex patterns and best practices.

© Copyright 2024. All rights reserved