Search code examples
vue.jsvuexvue-reactivity

Computed property returning state variable isn't reactive


For a hangman game I have a Word.vue component in which I'm trying to initialise an array named wordToGuessAsArray containing n empty items (n = number of letters in word to guess):

<template>
  <section>
    <div v-for="(letter, i) in wordToGuessAsArray" :key="i">
    </div>
  </section>
</template>

<script>
export default {
  computed: {
    wordToGuessAsArray () {
      return this.$store.state.wordToGuessAsArray
    }
  },
  mounted () {
    const wordToGuess = 'strawberry'
    for (var i = 0; i < wordToGuess.length; i++) {
      this.$store.commit('SET_WORD_AS_ARRAY_PUSH')
    }
  }
}
</script>

Below is the content of my store relevant to this question:

state: {
  wordToGuessAsArray: [],
},
mutations: {
  SET_WORD_AS_ARRAY_PUSH (state) {
    state.wordToGuessAsArray.push('')
  },
  SET_WORD_AS_ARRAY (state, value) {
    state.wordToGuessAsArray[value.i] = value.letter
  }
}

My problem is the following. In my Keyboard.vue component, when user picks a letter that does indeed belong to the word to guess, I update my state thus:

this.$store.commit('SET_WORD_AS_ARRAY', { letter, i })

I expect this mutation to update the word in my Word.vue component here:

<div v-for="(letter, i) in wordToGuessAsArray" :key="i">

Yet it doesn't. wordToGuessAsArray seems non reactive, why?


Solution

  • It is because state.wordToGuessAsArray[value.i] = value.letter is not reactive. Because Vue.js only watch array methods like push or splice.

    You need to do this.$set(state.wordToGuessAsArray, value.i, value.letter);

    Or in Vuex : Vue.set(state.wordToGuessAsArray, value.i, value.letter); and import Vue in your file.

    Read more here :

    https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

    Vuejs and Vue.set(), update array