Vuex getter with an argument and computed property - vue.js

I'm having trouble understanding how the code from a tutorial works.
I have the EventComponent component, which displays information about the event.
It uses a computed property which accesses Vuex store.
<h4>This event is {{ getEvent(1) }}.</h4>
export default {
computed: {
getEvent() {
return this.$store.getters.getEventById
}
}}
And this is my Vuex index.js file:
export default createStore({
state: {
events: [{id: 1, title: "Last day"}]
},
mutations: {},
getters: {
getEventById: state => id => {
return state.events.find(event => event.id === id)
}
},
actions: {},
modules: {}
})
The event info is displayed correctly. However, I'm confused by
How the computed property is able to accept an argument
How that argument is passed to the store getter, when the getter is not explicitly called with that argument
Could you help me understand this?

How the computed property is able to accept an argument
Since getEvent just returns this.$store.getters.getEventById (which is a getter for a function), getEvent also returns a function, and can therefore be called the exact same way.
How that argument is passed to the store getter, when the getter is not explicitly called with that argument
Actually, the getter is indeed being called with that argument. As mentioned above getEvent is effectively an alias for this.$store.getters.getEventById, so getEvent(1) is the same as this.$store.getters.getEventById(1).

Return a function from the computed property that takes the id as parameter:
<h4>This event is {{ getEvent(1) }}.</h4>
export default {
computed: {
getEvent() {
return (id)=>this.$store.getters.getEventById(id)
}
}}

Related

Computed properties and Vuex

I'm a little confused on how computed properties work with Vuex. I'm using a computed getter:
var selectDisplayValues = computed({
get() {
return store.getters['expense/getSelectDisplayValues'];
}
});
When the store data changes the computed prop also changes. So far so clear.
When now assigning a new value to the computed property - the value inside the store also changes. Not just the local value of the property. Why is that so? Won't I need a setter inside the computed prop to do so?
EDIT:
I'm assigning the new values like this.
selectDisplayValues.value[`inputData[${props.index}][${props.attribute}]`] = {placeholder_value: "Bitte wählen...", value: "", reassigned: false};
Also I'm using a v-model on a select dropdown for changing them according to the options value.
A new value wasn't assigned but existing value was mutated.
Getter-only computed ref has read-only value property that contains unmodified value.
If the intention is to make ref value deeply read-only, this needs to be explicitly done:
const selectDisplayValues = readonly(toRef(store.getters, 'expense/getSelectDisplayValues'))
I would personaly recommand using mapGetters from vuex : the mapgetters helper
I works like this :
You decalre a getter un your vuex store :
const store = createStore({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos (state) {
return state.todos.filter(todo => todo.done)
}
}
})
And in your vue component :
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
...mapGetters({
doneCount: 'doneTodosCount'
})
}
}
You can then access value from your getter with this.doneCount
If the store change the computed value wil automatically change

Vuex Getter Hook with Params

I defined a vuex getter function with parameter like this:
const getters = {
getProjectById: (state) => (id) => {
return state.projects.find(project => project.id === id)
}
}
Now, i want to use this getter in my component, but i couldn't find a way to pass the parameter to the getter.
Here is my getter hook computed property:
computed: {
...mapGetters(["currentUserPhoto","getProjectById"])
},
Is it possible to pass Id parameter which is come from router, to "getProjectId" getter? If is possible, what is the best way to do it?
Add another computed property called projectById which takes the route param as parameter and returns the project :
computed: {
...mapGetters(["currentUserPhoto","getProjectById"]),
projectById(){
return this.getProjectById(this.$route.params.id)
}
},

Changing getter value using state value in Vuex

I have this getter that get the value of one item in the state:
boxdata: state => {
return state.boxchart.data
},
Now I have another item in state that I use to change the value of getter
Currently I do this when component is mounted but it seems that the data sometimes loads but sometimes does not:
computed: {
...mapGetters(["boxdata"]),
...mapState(['reference_fc'])
},
mounted() {
this.boxdata[0].chartOptions.series[0].data[0]=this.reference_fc.NSR.values
}
So I wonder how can I ensure that the boxdata getter is already updated on the first time that the component loads?
Vue cannot detect array element assignments. This is explained in Caveats.
Try this instead:
this.$set(this.boxdata[0].chartOptions.series[0].data, 0, this.reference_fc.NSR.values)
You shouldn't mutate data using getters. You should use mutations.
Getters are only to get derived state based on store state. see here
In your store :
mutations: {
setBoxdata(state, value) {
state.boxchart.data[0].chartOptions.series[0].data[0] = value;
}
}
In your component :
computed: {
...mapMutations("setBoxdata")
},
mounted() {
this.setBoxData(this.reference_fc.NSR.values);
}

VueJS: Property or method "tagNbr" is not defined on the instance but referenced during render. Make sure that this property is reactive

I'm trying to get a value from a VueX store during render at the render of my component. What I see is that i firstly get the error above, and then, the value is correctly updated on the component because I think that the state is well reactive but not initialized when component is rendered.
How can i avoid this error ?
template:
<span class="kt-widget17__desc">
{{ carsNumber }}
</span>
script:
export default {
data() {
return {
carsNumber: this.currentGarage.numberOfTags
};
},
computed: {
...mapGetters(["currentGarage"]),
}
};
Error:
Property or method "carsNumber" is not defined on the instance but
referenced during render. Make sure that this property is reactive..
What I did is I created a setter and getter in computed property, in your case carsNumber instead of putting it inside the data property.
computed: {
...mapGetters(["currentGarage"]),
carsNumber: {
get(){
return this.currentGarage.numberOfTags
},
set(newVal){ // setter can be excluded if not used
// you can call this.$store.commit('yourMutation', yourValue)
}
}
}

How to pass variable from Vuex store to a function as value?

So I am working with what would appear to be a simple issue, but it is eluding me this evening. I have a value that is set in a Vuex store. In my component file, I declare a constant where the value is retrieved from the store. Everything up to this point works perfectly.
Then, upon submitting a form in the component a script function is run. Within that function, I need to pass the value from the Vuex store along with a couple of other arguments to another function. The function gets call, the arguments are passed, and it all works as expected.
However ... I am getting console errors stating ...
Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] do not mutate vuex store state outside mutation handlers.
What is the correct what to retrieve a value from the Vuex store and then pass that value to a function?
Some more detail here ... Page 1 stores an object representing a CognitoUser in the store using a mutation function which works as expected, then transitions to Page 2. Page 2 retrieves the object from the store (tried both the data and computed methods mentioned below as well as using the getter directly in the code - all fail the same). Within a method on Page 2, the object from the store is accessible. However, that method attempts to call the Amplify completeNewPassword method, passing the CongnitoUser object as an argument. This is the point that the error appears stating that the mutation handler should be used even though there is no change to the object on my end.
....
computed: {
user: {
get(){
return this.$store.getters[ 'security/localUser' ]
},
set( value ){
this.$store.commit( 'security/setLocalUser', value )
}
}
},
....
methods: {
async submitForm(){
this.$Amplify.Auth.completeNewPassword( this.user, this.model.password, this.requiredAttributes )
.then( data => {
....
This is almost certainly a duplicate question. You can refer to my answer here.
Basically you should pass the Vuex value to a local data item and use that in your component function. Something like this.
<script>
export default {
data: () => ({
localDataItem: this.$store.getters.vuexItem,
})
methods: {
doSomething() {
use this.localDataItem.here
}
}
}
</script>
The canonical way of handling this by using computed properties. You define a computed property with getter and setter and proxy access to vuex thru it.
computed: {
localProperty: {
get: function () {
return this.$store.getters.data
},
set: function (val) {
this.$store.commit(“mutationName”, val )
}
}
}
Now you can use localProperty just as we use any other property defined on data. And all the changes get propagated thru the store.
Try if this work
<template>
<div>
<input :value="user" #change="onChangeUser($event.target.value)"></input>
</div>
</template>
<script>
computed: {
user() {
return this.$store.getters[ 'security/localUser' ]
}
},
methods: {
onChangeUser(user) {
this.$store.commit( 'security/setLocalUser', user );
},
async submitForm(){
this.$Amplify.Auth.completeNewPassword( this.user, this.model.password, this.requiredAttributes )
.then( data => {
...
}
</script>