Search code examples
javascriptvue.jsvuex

Vuex mutation updates state, computed property never reflects update in markup


This issue hasn't been touched in a while but i'm running into something confusing on my end when using a computed property for a textarea value.

I have a textarea where you give input text and on input it updates the input text in vuex:

<textarea
ref="inputText"
:value="getInputText"
@input="setInputText"
class="textarea"
placeholder="Your message goes in here"
></textarea>

On the click of a button to translate the text I call a handleInput method.

handleInput() {
    this.$store.dispatch("translateEnglishToRussian");
},

In my store I have my translateEnglishToRussian action:

translateEnglishToRussian({ commit }) {
    const TRANSLATE_API = "https://XXXXXXXX.us-east-1.amazonaws.com/prod/YYYY/";
    const data = JSON.stringify({ english: this.state.inputText });

    this.$axios
    .$post(TRANSLATE_API, data)
    .then(data => {
        commit("setOutputText", data.translatedText);
        commit("setMP3Track", data.mp3Path);
    })
    .catch(err => {
        console.log(err);
    });
}

I see it call setOutputText mutation with the payload of translated text, in my vue dev tools I see the correct state with the translated text. However, my second text area that's being used purely to display the translated text never updates!

Output textarea:

<textarea
disabled
ref="outputText"
:value="getOutputText"
class="textarea"
></textarea>

Its value is bound to a computed property called getOutputText:

getOutputText() {
    return this.$store.state.outputText;
}

What am i doing wrong here! Any advice is appreciated. I thought this should be fine since i'm using commit in my vuex action in a synchronous way (inside the then() block).

Edit: I have the same result if I also try using v-model. The initial output text from vuex state is rendered there on page load. When I translate, I see the update in Vue Dev Tools correctly, but the text in the text area never re-renders.

Edit #2: Here is my setOutputText mutation:

  setOutputText(state, payload) {
    console.log(`state - set output - ${payload}`);
    state.outputText = payload;
  },

Solution

  • After looking at the vue docs for Multiline text, you should replace :value="getOutputText" with v-model="getOutputText".

    Because it's computed property, to use it in v-model you need to add get and set to your computed property

    <textarea
      disabled
      ref="outputText"
      v-model="getOutputText"
      class="textarea"
    ></textarea>
    

    EDIT: Per @Stephen Tetreault comment, v-model didn't work for him, but :value did solve the problem at the end.

    computed: {
      getOutputText: {
        // getter
        get: function () {
          return this.$store.state.outputText;
        },
        // setter
        set: function (newValue) {
          // there is no need to set anything here
        }
      }
    }