2
votes

Hi everyone I am I having some difficulty when working with Nuxt and Vuex.

I am trying to run through the example Vuex / Nuxt Classic Mode. https://nuxtjs.org/guide/vuex-store/

After clicking my increment button I dont see the number go up. My page just stays at 0, I can see within the console that the state knows the number is no longer 0 but not on the screen, as if it doesnt know to be reactive.

My assumption is that I have miss configured something somewhere and my 0 is not the actual state, but I created some copy of it somehow.

Here is my button within my template.

<button @click="inc">{{ counter }}</button>

Here is my inc function within my methods.

inc () {
  this.$store.commit('increment')
},

Here is my computed

computed: {
  counter () {
    return this.$store.getters.counter
  }
}

Here is my Vuex/index.js file contained within the store folder.

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const createStore = () => {
  return new Vuex.Store({
    state: () => ({
      counter: 0
    }),
    getters: {
       counter: state => state.counter
    },
    mutations: {
      increment (state) {
        state.counter++
      }
    }
  })
}

export default createStore

Commercial Photography

Update: Included more code snippets, and replied to existing comments.

@Boussadjra Brahim @xaviert, thank you both for weighing in, I appreciate the assistance.

@Boussadjra Brahim - Yes, I had tried using an action that called the mutation, that didnt seem to get me there either. I also tried adjusting the state via the action alone, and wasnt able to make any changes, however that seems correct, as I am under the impression that actions call mutations to make state changes and do not themselves do so, please correct me if you know more. I am 100% open to the idea that I did not attempt it correctly. Below is that action that didnt do anything and the one that called the mutation

actions: {
  increment (state) {
    state.counter++
  }
},   

And here is the version with the action calling the mutation.

actions: {
  incrementCounterUp () {
    this.commit('increment')
  }
},

@xaviert - I have tried starting the server over, and have also tried to see if an nuxt build followed by a firebase serve, to see if maybe that helped. It did not. My normal server start is 'npm run dev'. In hopes that you/anyone else may be able to find my mistake below is my full _id.vue component and also my nuxt.config.js file as maybe that's it. Its still pretty raw and could use a lot of refactoring so hope you can sort through it well enough.

_.id.vue

<template>
  <div class="product">
    <div class="product-image">
      <div class="product-image-img">
        <img v-bind:src="product.image_file" width="450px;"/>
      </div>
    </div>
    <div class="product-details-wrapper">
      <div class="product-details">
        <h1>
          <div v-if="this.$route.query.editPage">
            <textarea @input="updateTextArea" ref="textarea2" v-model="product.item_name" type="text" />
          </div>
          <div v-else>{{product.item_name}}</div>
        </h1>
        <div class="product-description">
          <div class="product-description-text" v-if="this.$route.query.editPage">
            <textarea @input="updateTextArea" ref="textarea" v-model="product.description" type="text" />
          </div>
          <div class="product-description-text" v-else v-html="product.description"></div>
        </div>
        <p class="product-brand"><strong>Brand - </strong> {{product.brand_name}}</p>
        <hr />
        <div class="product-price">
          <div v-if="this.$route.query.editPage">
            <strong>Original Price - </strong>
            <input v-model="product.msrp" type="text" />
          </div>
          <div v-else class="product-msrp">
            <strong>Original Price - </strong>
            <span class="strike">${{product.msrp}}</span>
          </div>
          <div v-if="this.$route.query.editPage">
            <strong>Sale Price - </strong>
            <input v-model="product.price" type="text" />
          </div>
          <div v-else class="product-sale-price">
            <strong>Sale Price - </strong>
            <span class="">${{product.price}}</span>
          </div>
          <div class="product-price">
            Quantity x
            <input @input="updateQuantity" v-model="quantity" min="1" class="" type="number" value="1" />
          </div>
          <button @click="inc">{{ counter }}</button>
        </div>
      </div>
    </div>
    <div v-if="this.$route.query.editPage" class="update-product">       <button @click="updateProduct(product)">Update</button></div>
    <div class="footer">
      <router-link to="/privacy-policy" target="_blank">Privacy</router-link> |
      <router-link to="/terms" target="_blank">Terms</router-link>
    </div>

  </div>
</template>

<script>
// @ is an alias to /src

import firebase from '@/services/fireinit'
import foo from '@/components/foo'
const db = firebase.firestore()
export default {
  name: 'ProductPage',
  head () {
    return {
      title: this.product.item_name
    }
  },
  components: {
    foo
  },
  data: function () {
    return {
      product: {},
      image: '',
      name: 'Checkout',
      description: '',
      currency: 'USD',
      amount: '',
      msrp: '',
      quantity: 1
    }
  },
  methods: {
    inc () {
      this.$store.dispatch('incrementCounterUp', true)
    },
    updateProduct: function (product) {
      db.collection('products').doc(product.item_id).set(product)
        .then(function () {
          console.log('Document successfully written!')
        })
        .catch(function (error) {
          console.error('Error writing document: ', error)
        })
    },
    updateQuantity () {
      this.product.msrp = (this.quantity * this.product.orgMsrp)
      this.product.msrp = Math.round(100 * this.product.msrp) / 100
      this.product.price = this.quantity * this.product.orgPrice
      this.product.price = Math.round(100 * this.product.price) / 100
    },
    updateTextArea () {
      this.$refs.textarea.style.minHeight = this.$refs.textarea.scrollHeight + 'px'
      this.$refs.textarea2.style.minHeight = this.$refs.textarea2.scrollHeight + 'px'
    }
  },
  async asyncData({app, params, error}) {
    const ref = db.collection("products").doc(params.id)
    let snap
    let thisProduct = {}
    try {
      snap = await ref.get()
      thisProduct = snap.data()
      thisProduct.orgMsrp =  thisProduct.msrp
      thisProduct.orgPrice =  thisProduct.price
    } catch (e) {
      // TODO: error handling
      console.error(e)
    }
    return {
      product: thisProduct
    }
  },
  mounted () {
    if(this.$refs.textarea) {
      this.$refs.textarea.style.minHeight = this.$refs.textarea.scrollHeight + 'px'
      this.$refs.textarea2.style.minHeight = this.$refs.textarea2.scrollHeight + 'px'
    }
  },
  computed: {
    counter () {
      return this.$store.getters.counter
    }
  }
}
</script>


<style lang="less">
body {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
  margin: 0
}
p{
  margin-top: 1em;
  margin-bottom: 1em;
}
html, body, #__nuxt, #__layout, .default,  .product{
  height: 100%;
}
.product {
  justify-content: center;
  display: flex;
  max-width: 1150px;
  margin: 0 auto;
  flex-wrap: wrap;
  align-items: center;
  padding: 0 24px;
  &-price{
    input {
      border: 1px solid;
      padding: 0 .3em;
      text-align: center;
      width: 50px;
    }
  }
}
  .product-details{
    width: 100%;
    textarea {
      width: 100%;
      font-size: inherit;
      color: inherit;
      font-family: inherit;
      font-weight: inherit;
      height: initial;
      resize: none;
      background-color: transparent;
      border: none;
    }
    h1{
      font-size: 1.9rem;
      margin: 15px 0 20px;
    }
    hr{
      width: 50%;
      margin: .5rem 0px;
    }
    p{

    }
  }
  .product-description-text{
    margin: 10px 0;
  }
  .product-image, .product-details-wrapper{
    align-items: center;
    display: flex;
    justify-content: center;
  }
  .product-details-wrapper{
    flex: 0 1 535px;
  }
  .product-image{
    flex: 0 1 535px;
    img{
      width: 100%;
    }
  }
  .product-price{
    .strike{
      text-decoration: line-through;
    }
    button{
      display: flex;
      width: 150px;
      height: 50px;
      border-radius: 5px;
      justify-content: center;
      font-size: 24px;
      margin-top: 20px;
      &:hover{
        cursor: pointer;
        background-color: #f1f1f1;
        box-shadow: 3px 3px 11px -1px rgba(0, 0, 0, 0.48);
      }
    }
  }
  .product-sale-price{
    color: #f30000;
  }
  .footer {
    flex: 1 1 100%;
    text-align: center;
    color: #ccc;
    margin-top: 25px;
    padding: 15px;
    a {
      color: #ccc;
      text-decoration: none;
      &:hover{
        text-decoration: underline;
      }
    }
  }
  .update-product{
    position: absolute;
    top: 0;
    text-align: center;
  }

</style>

nuxt.confgs.js

const pkg = require('./package')
const { STRIPE_TOKEN } = process.env;

module.exports = {
  vue: {
    config: {
      productionTip: false,
      devtools: true
    }
  },
  buildDir: './functions/nuxt',
  mode: 'universal',

  /*
  ** Headers of the page
  */
  head: {
    title: pkg.name,
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: pkg.description }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },

  /*
  ** Customize the progress-bar color
  */
  loading: { color: '#fff' },

  /*
  ** Global CSS
  */
  css: [
  ],

  /*
  ** Plugins to load before mounting the App
  */

  /*
  ** Nuxt.js modules
  */
  modules: [
    // Doc: https://github.com/nuxt-community/axios-module#usage
    '@nuxtjs/axios',
    'nuxt-stripe-module'
  ],
  stripe: {
    version: 'v3',
    publishableKey: 'pk_test_XXX',
  },
  /*
  ** Axios module configuration
  */
  axios: {
    // See https://github.com/nuxt-community/axios-module#options
  },

  /*
  ** Build configuration
  */
  build: {
    /*
    ** You can extend webpack config here
    */
    publicPath: '/public/',
    vendor: [],
    extractCSS: true,
    bable: {
      presets: [
        'es2015',
        'stage-8'
      ],
      plugins: [
        ['transform-runtime', {
          'polyfill': true,
          'regenerator': true
        }]
      ]
    },
    extend (config, { isDev }) {
      if (isDev && process.client) {
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/
        })
      }
    },
    router: {
      middleware: 'router-auth'
    }
  },
  plugins: [
    { src: '~/plugins/fireauth', ssr: true }
  ]
}

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const createStore = () => {
  return new Vuex.Store({
    state: () => ({
      counter: 0
    }),
    actions: {
      incrementCounterUp () {
        this.commit('increment')
      }
    },
    getters: {
      counter: state => state.counter
    },
    mutations: {
      increment (state) {
        state.counter++
      }
    }
  })
}

export default createStore
1
did you try actions instead of the direct mutations?Boussadjra Brahim
Your example seems to work fine. Did you try restarting the Nuxt webserver? Alternatively, post the actual Vue component file, perhaps something silly is missing.xaviert
Couple of things you could try. In your action have a destructured commit as a parameter like this incrementCounterUp ({commit}) { commit('increment') } and maybe not pass the parameter 'true' in your inc method. Just this.$store.dispatch('incrementCounterUp')Andrew1325

1 Answers

2
votes

At the end of the day, I was not able to identify exactly what in my application was the error.

I assume that my during my initialization, configuration or development I touched something that should not have been touched, installed something that should not have be installed, messed with a package I should not have or was to bold in my nuxt.config.js changes.

I created a new nuxt app following the same install instructions. https://nuxtjs.org/guide/installation/

Moved the above _id.vue component exactly as it is and once I got dependencies updated it worked perfectly as seen in the image below.

Thank you very much @Boussadjra Brahim, @xaviert, @Andrew1325 for you assistance.

enter image description here