admin管理员组

文章数量:1026989

I am using the mapGetters helper from VueX but i have some problem only on the first load of the page, it's not reactive... Let me show you :

my html template triggering the change :

<input type="number" value="this.inputValue" @change="this.$store.dispatch('setInputValue', $event.target.value)">

my store receiving the value

{
    state: {
        appValues: {
            inputValue: null
        },
    },
    getters: {
        getInputValue: (state) => {
            return state.appValues.inputValue;
        },
    },
    mutations: {
        setInputValue(state, value) {
            state.appValues.inputValue = value;
        },
    },
    actions: {
        setInputValue(context, payload) {
            return new Promise((resolve, reject) => {
                contextmit('setInputValue', payload);
                resolve();
            });
        },
    }
}

and then my ponent listening the store :

import {mapGetters} from 'vuex';

puted: {
    ...mapGetters({
        inputValue: 'getInputValue',
    }),
}
watch: {
    inputValue: {
        deep: true,
        immediate: true,
        handler(nVal, oVal) {
            console.log("inputValue", nVal, oVal);
        }
    },
}

So now, when i first load the page I get this console.log "inputValue" null undefined which is totally normal because as I have nothing in my store it gaves me the default value null.

But now it's the weird part. I start changing the input value and I don't have nothing appearing in my console. Nothing is moving...

Then I reload the page and on the load I get this console.log "inputValue" 5 undefined (5 is the value I entered previously) so as you can see, when I was changing the input previously, it was well keeping the value in the store but the puted value was not updating itself...

Ans now, when I change the value of the input I have my console log like this "inputValue" 7 5 so it's working as I would like it to work from the start...

What do I do wrong? Why on the first load the puted value not reactive?

Thanks for your answers...

I am using the mapGetters helper from VueX but i have some problem only on the first load of the page, it's not reactive... Let me show you :

my html template triggering the change :

<input type="number" value="this.inputValue" @change="this.$store.dispatch('setInputValue', $event.target.value)">

my store receiving the value

{
    state: {
        appValues: {
            inputValue: null
        },
    },
    getters: {
        getInputValue: (state) => {
            return state.appValues.inputValue;
        },
    },
    mutations: {
        setInputValue(state, value) {
            state.appValues.inputValue = value;
        },
    },
    actions: {
        setInputValue(context, payload) {
            return new Promise((resolve, reject) => {
                context.mit('setInputValue', payload);
                resolve();
            });
        },
    }
}

and then my ponent listening the store :

import {mapGetters} from 'vuex';

puted: {
    ...mapGetters({
        inputValue: 'getInputValue',
    }),
}
watch: {
    inputValue: {
        deep: true,
        immediate: true,
        handler(nVal, oVal) {
            console.log("inputValue", nVal, oVal);
        }
    },
}

So now, when i first load the page I get this console.log "inputValue" null undefined which is totally normal because as I have nothing in my store it gaves me the default value null.

But now it's the weird part. I start changing the input value and I don't have nothing appearing in my console. Nothing is moving...

Then I reload the page and on the load I get this console.log "inputValue" 5 undefined (5 is the value I entered previously) so as you can see, when I was changing the input previously, it was well keeping the value in the store but the puted value was not updating itself...

Ans now, when I change the value of the input I have my console log like this "inputValue" 7 5 so it's working as I would like it to work from the start...

What do I do wrong? Why on the first load the puted value not reactive?

Thanks for your answers...

Share Improve this question edited Jul 11, 2019 at 10:08 Rob 15.2k30 gold badges48 silver badges73 bronze badges asked Jul 11, 2019 at 9:48 Simon TrichereauSimon Trichereau 80912 silver badges24 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 1

I think the best way to solve this issue is to store a local variable with a watcher, and then update vuex when the local is changed:

On your ponent:

<input type="number" v-model="value">

data() {
    return {
        value: ''
    };
},

puted: {
    ...mapGetters({
        inputValue: 'getInputValue'
    })
}

watch: {
    value(value){
        this.$store.dispatch('setInputValue', value);
    },

    inputValue(value) {
        console.log('inputValue', value);
    }
},

created() {
    // set the initial value to be the same as the one in vuex
    this.value = this.inputValue;
}

Please take a look at this sample: https://codesandbox.io/s/vuex-store-ne3ol

Your mistake is, you are using this keyword in template. One shouldn't use this in template code.

<input
      type="number"
      value="inputValue"
      @change="$store.dispatch('setInputValue', $event.target.value)"
    >

Bonus tip: It is redundant to use a getter to return the default state if you can just use mapState to return the state.

There are a few small mistakes in the template. It should be this:

<input type="number" :value="inputValue" @change="$store.dispatch('setInputValue', $event.target.value)">

I've removed the this. in a couple of places and put a : out the front of value. Once I make these changes everything works as expected. The this.$store was causing console errors for me using Vue 2.6.10.

I would add that you're using the change event. This is the standard DOM change event and it won't fire until the field blurs. So if you just start typing you won't see anything happen in the console. You'd be better off using input if you want it to update on every keystroke. Alternatively you could use v-model with a getter and setter (see https://vuex.vuejs/guide/forms.html#two-way-puted-property).

My suspicion is that when you were reloading the page that was triggering the change event because it blurred the field.

Ok, so ... I found the problem and it was not relative to my examples, I can't really explain why, but I'll try to explain how :

In my store I have the next method :

mutations: {
    deleteAppValues(state) {
        state.appValues = null;
    }
}

I was using this one on the Logout, or when the user first es on the pageand was not logged-in... So what was going-on?

  1. The User first load the page, the store is initializing well, and the index inputValue is initialized with null value, so it exists...
  2. ... But as the User is not logged, I destroy the store so now the inputValue is not equals to null, it just doesn't exist...
  3. Trying to use mapGetters on something that don't exists, the reactivity won't work, so if I dispatch a change, the store key will be created, but as the mapGetters was initialized with an inexisting key, it doesn't listen the reactivity...
  4. After reloading the page, the key now exists in the store so the getter can be attached to it and so now everything working fine...

This is exactly the explaination of what was going wrong about my code... So to make it works fine, I just changed my destruction mutation to :

mutations: {
    deleteAppValues(state) {
        state.appValues = {
            inputValue: null,
        };
    }
}

Like this, the inputValue key of the store object will always exists and so the getter won't lose his reactivity...

I tryed to make a simple concise question but that made me forgot the bad part of my code, sorry.

I am using the mapGetters helper from VueX but i have some problem only on the first load of the page, it's not reactive... Let me show you :

my html template triggering the change :

<input type="number" value="this.inputValue" @change="this.$store.dispatch('setInputValue', $event.target.value)">

my store receiving the value

{
    state: {
        appValues: {
            inputValue: null
        },
    },
    getters: {
        getInputValue: (state) => {
            return state.appValues.inputValue;
        },
    },
    mutations: {
        setInputValue(state, value) {
            state.appValues.inputValue = value;
        },
    },
    actions: {
        setInputValue(context, payload) {
            return new Promise((resolve, reject) => {
                contextmit('setInputValue', payload);
                resolve();
            });
        },
    }
}

and then my ponent listening the store :

import {mapGetters} from 'vuex';

puted: {
    ...mapGetters({
        inputValue: 'getInputValue',
    }),
}
watch: {
    inputValue: {
        deep: true,
        immediate: true,
        handler(nVal, oVal) {
            console.log("inputValue", nVal, oVal);
        }
    },
}

So now, when i first load the page I get this console.log "inputValue" null undefined which is totally normal because as I have nothing in my store it gaves me the default value null.

But now it's the weird part. I start changing the input value and I don't have nothing appearing in my console. Nothing is moving...

Then I reload the page and on the load I get this console.log "inputValue" 5 undefined (5 is the value I entered previously) so as you can see, when I was changing the input previously, it was well keeping the value in the store but the puted value was not updating itself...

Ans now, when I change the value of the input I have my console log like this "inputValue" 7 5 so it's working as I would like it to work from the start...

What do I do wrong? Why on the first load the puted value not reactive?

Thanks for your answers...

I am using the mapGetters helper from VueX but i have some problem only on the first load of the page, it's not reactive... Let me show you :

my html template triggering the change :

<input type="number" value="this.inputValue" @change="this.$store.dispatch('setInputValue', $event.target.value)">

my store receiving the value

{
    state: {
        appValues: {
            inputValue: null
        },
    },
    getters: {
        getInputValue: (state) => {
            return state.appValues.inputValue;
        },
    },
    mutations: {
        setInputValue(state, value) {
            state.appValues.inputValue = value;
        },
    },
    actions: {
        setInputValue(context, payload) {
            return new Promise((resolve, reject) => {
                context.mit('setInputValue', payload);
                resolve();
            });
        },
    }
}

and then my ponent listening the store :

import {mapGetters} from 'vuex';

puted: {
    ...mapGetters({
        inputValue: 'getInputValue',
    }),
}
watch: {
    inputValue: {
        deep: true,
        immediate: true,
        handler(nVal, oVal) {
            console.log("inputValue", nVal, oVal);
        }
    },
}

So now, when i first load the page I get this console.log "inputValue" null undefined which is totally normal because as I have nothing in my store it gaves me the default value null.

But now it's the weird part. I start changing the input value and I don't have nothing appearing in my console. Nothing is moving...

Then I reload the page and on the load I get this console.log "inputValue" 5 undefined (5 is the value I entered previously) so as you can see, when I was changing the input previously, it was well keeping the value in the store but the puted value was not updating itself...

Ans now, when I change the value of the input I have my console log like this "inputValue" 7 5 so it's working as I would like it to work from the start...

What do I do wrong? Why on the first load the puted value not reactive?

Thanks for your answers...

Share Improve this question edited Jul 11, 2019 at 10:08 Rob 15.2k30 gold badges48 silver badges73 bronze badges asked Jul 11, 2019 at 9:48 Simon TrichereauSimon Trichereau 80912 silver badges24 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 1

I think the best way to solve this issue is to store a local variable with a watcher, and then update vuex when the local is changed:

On your ponent:

<input type="number" v-model="value">

data() {
    return {
        value: ''
    };
},

puted: {
    ...mapGetters({
        inputValue: 'getInputValue'
    })
}

watch: {
    value(value){
        this.$store.dispatch('setInputValue', value);
    },

    inputValue(value) {
        console.log('inputValue', value);
    }
},

created() {
    // set the initial value to be the same as the one in vuex
    this.value = this.inputValue;
}

Please take a look at this sample: https://codesandbox.io/s/vuex-store-ne3ol

Your mistake is, you are using this keyword in template. One shouldn't use this in template code.

<input
      type="number"
      value="inputValue"
      @change="$store.dispatch('setInputValue', $event.target.value)"
    >

Bonus tip: It is redundant to use a getter to return the default state if you can just use mapState to return the state.

There are a few small mistakes in the template. It should be this:

<input type="number" :value="inputValue" @change="$store.dispatch('setInputValue', $event.target.value)">

I've removed the this. in a couple of places and put a : out the front of value. Once I make these changes everything works as expected. The this.$store was causing console errors for me using Vue 2.6.10.

I would add that you're using the change event. This is the standard DOM change event and it won't fire until the field blurs. So if you just start typing you won't see anything happen in the console. You'd be better off using input if you want it to update on every keystroke. Alternatively you could use v-model with a getter and setter (see https://vuex.vuejs/guide/forms.html#two-way-puted-property).

My suspicion is that when you were reloading the page that was triggering the change event because it blurred the field.

Ok, so ... I found the problem and it was not relative to my examples, I can't really explain why, but I'll try to explain how :

In my store I have the next method :

mutations: {
    deleteAppValues(state) {
        state.appValues = null;
    }
}

I was using this one on the Logout, or when the user first es on the pageand was not logged-in... So what was going-on?

  1. The User first load the page, the store is initializing well, and the index inputValue is initialized with null value, so it exists...
  2. ... But as the User is not logged, I destroy the store so now the inputValue is not equals to null, it just doesn't exist...
  3. Trying to use mapGetters on something that don't exists, the reactivity won't work, so if I dispatch a change, the store key will be created, but as the mapGetters was initialized with an inexisting key, it doesn't listen the reactivity...
  4. After reloading the page, the key now exists in the store so the getter can be attached to it and so now everything working fine...

This is exactly the explaination of what was going wrong about my code... So to make it works fine, I just changed my destruction mutation to :

mutations: {
    deleteAppValues(state) {
        state.appValues = {
            inputValue: null,
        };
    }
}

Like this, the inputValue key of the store object will always exists and so the getter won't lose his reactivity...

I tryed to make a simple concise question but that made me forgot the bad part of my code, sorry.

本文标签: javascriptReactivity problem with mapGetters only on first loadStack Overflow