Search code examples
vue.jsvuejs3nuxt.jsvuex

How to use VueX 4 in nuxt 3 project


I am fairly new to Vue, but had started my project in Vue 3 when after I realized that I wanted to optimize for SEO, so I decided to move to Nuxt. However I have found it a bit challenging to move my application to Nuxt, I read on a guide that nuxt has automatic vuex integration and I just have to make a store folder with my store then it will automatically find it, however this has not been the case, I am just wondering if I am missing something when trying to use my original vuex store in my new Nuxt project, maybe I have to edit the plugins? thanks

my store:

export const state = () => ({
  alloutActualReview: "",
  theGood: "",
  theBad: "",
  infoBoxes: {
    labs: false,
    group: false,
    exam: false,
    test: false
  },
  reviews: null,
})

export const actions = {
  async fetchReview({ commit }, reviewId) {
    return fetch(`requst_ip/myapp/api/get_reviews/${reviewId}`)
      .then(response => response.json())
      .then(data => {
        commit('setReviews', data);
      });
  }
}
export const mutations = {
  setAlloutReview(state, reviewData){
    state.alloutActualReview = reviewData
  },
  setTheGood(state, reviewData){
    state.theGood = reviewData
  },
  setTheBad(state, reviewData){
    state.theBad = reviewData
  },
  updateInfoBox(state, { key, value }) {
      state.infoBoxes[key] = value;
  },
  setReviews(state, review) {
    state.reviews = review;
  }
}
export const getters = {
}

the page componant:

<!-- pages/reviews.vue -->

<template>
  <div>
    <h1 v-for="review in reviews">{{review.name}}</h1>
  </div>
</template>

<script>
export default {
  name: 'ReviewsComponent',

  computed: {
    // Access the reviews from the store
    reviews() {
      return this.$store.state.reviews;
    }
  },

  mounted() {
    // Dispatch the fetchReviews action when the component is mounted
    this.fetchReviews();
  },

  methods: {
    async fetchReviews() {
      try {
        await this.$store.dispatch('fetchReviews', 6);
      } catch (error) {
        console.error('Error fetching reviews:', error);
      }
    }
  }
}
</script>

The error: [nitro] [unhandledRejection] TypeError: Cannot read properties of undefined (reading 'state')

I have tried using useStore instead to access the store but that did not work.

I have also tried creating a plugin an putting my store in the plugin as suggested by but this did not work either.


Solution

  • Nuxt will not import and use vuex before it has successfully registered a vuex store. For this to happen, you need to create a store inside the store folder.

    You can follow this folder structure for best practise, if you are going to have multiple modules, for example (ui module, reviews, cart, user, notification etc.)

    Source: https://v2.nuxt.com/docs/directory-structure/store/

     src
        |-- store
        |   |-- index.js          // Root store file
        |   |-- getters.js        // Root getters file
        |   |-- mutations.js      // Root mutations file
        |   |-- actions.js        // Root actions file
        |   |-- modules           // Modules folder
        |       |-- module1
        |       |   |-- state.js         // Module-specific state
        |       |   |-- getters.js       // Module-specific getters
        |       |   |-- mutations.js     // Module-specific mutations
        |       |   |-- actions.js       // Module-specific actions
        |       |   |-- index.js         // Module entry point
        |       |
        |       |-- module2
        |           |-- state.js
        |           |-- getters.js
        |           |-- mutations.js
        |           |-- actions.js
        |           |-- index.js

    OR as sampled in docs:

     store/
    --| index.js
    --| ui.js
    --| shop/
    ----| cart/
    ------| actions.js
    ------| getters.js
    ------| mutations.js
    ------| state.js
    ----| products/
    ------| mutations.js
    ------| state.js
    ------| itemsGroup1/
    --------| state.js

    Note that actions, mutations and getters and spread in separate files for better readability.

    Look at this post for more info: Nuxt + Vuex - How do I break down a Vuex module into separate files?

    If this.$store is undefined as your error suggest. Vuex is not imported, and a modules has not been registered. Once this.$store is defined, your first module has been registered.