Unable to update the Vuex store and retrieve array - javascript

I'm dispatching an array of objects to the Veux store and trying to get the data using "getters" from Vuex. It returns undefined. It is however working for a boolean variable in the same Vuex. For the array, it is not giving a proper result
I am using Vuex to update an array of objects across vue components.
I am dispatching the array of objects
committing the array through "actions"
setting and updating the value through "mutations"
Declaring the array through "state"
finally, from the Vue component, accessing the array through "getters"
I expect Vuex to return the array of objects when I access using "getters"
The store code is as given below
export default new Vuex.Store({
state: {
loading: false,
compoData: []
},
mutations: {
setLoading(state, payload) {
state.loading = payload
},
setCompoData(state, payload) {
state.compoData = payload.data
}
},
actions: {
setLoading({
commit
}, payload) {
commit('setLoading', payload)
},
setCompoData({
commit
}, payload) {
commit('setCompoData', payload)
},
},
getters: {
loading(state) {
return state.loading
},
compoaData(state){
return state.compoData
}
}
})
Vue component code is as given below. I am dispatching the array of objects "compoData" from the component to the store
someFunction(){
.....
some code
.....
this.$store.dispatch('setLoading',false)
this.$store.dispatch('setCompoData',{data:this.compoData})
},
Getting the values from store
gettingCompoData(){
console.log(this.$store.getters.compoData)
},
Though it works fine with the computed variable "loading", it does not work with the "compoData" array of objects .
I tested it with the below function
test(){
console.log(this.compoData, this.loading);
this.$store.dispatch('setCompoData',{data:this.compoData})
console.log(this.$store.getters.compoData, this.$store.getters.loading)
},
And this is the screenshot of the result I got this log result from the "test" function
It is clear that I am not sending an undefined array. But what I am getting from the store getters is undefined. Strangely, it is working for the boolean variable "loading" and it does return a valid result. I'm baffled as to why it does not return the array of objects. please help me out...
Any help would be appreciated. Thank you

you have a typo.
in store you defined a getter compoaData and when getting values from store you're looking for compoData

Related

On pushing object in array the vue ui is not getting updated

I am stucked in a problem where I have created a custom drag drop component which is working fine,
there is an array which is connected to vuex store, i have created the mutations to update or add new object inside the array that array is getting changed after drop operation but the ui is not getting changed
I am fetching that array using this.$store.getters['moduleName/functionName']
mutation.js=>
export default {
setNewValue(state, payload){
state.arr.push(payload);
}
}
handleDrop function =>
handleDrop(event, data){
let actionType = this.$store.getters["moduleName/getActionType"];
let obj;
let length = this.$store.getters["moduleName/getLengthOfArr"];
obj = {
id: length == 0 ? 1 : length + 1,
name: data.name,
isConditional: false,
...actionType[data.type],
yes: [],
no: [],
};
this.$store.commit("moduleName/setNewValue", obj);
action Type are some objects which i need to add based on data type provided
i guess it is due to reactivity of object properties or due to computed property which i am using in ui
computed : {
arr(){
return this.$store.getters['moduleName/getArray'];
}
}
getters.js
export default {
getArray(state){
return state.arr;
}
}
Thanks in advance
After some debugging i solved the problem as the problem was with rendering the data was getting updated and even store was getting updated
while rendering i was using the same object which was rendered previously but that made me so much confused due to vuejs' reactivity with computed property.

Vuex Getter Undefined

I am new to Vue.js and experiencing an issue with Vuex modules and Axios. I have a "post" component that retrieves a slug from the router and fetches data with Axios which is then retrieved with Vuex Getters.
I am able to retrieve data successfully but then I still see this error on my DevTools, "TypeError: Cannot read property 'name' of undefined"
Due to this error I am not able to pass this.post.name to Vue-Meta.
Codes
Post.vue
computed: {
...mapGetters(["post"]),
},
mounted() {
const slug = this.$route.params.slug;
this.fetchPost({ slug: slug });
},
methods: {
...mapActions(["fetchPost"]),
/store/modules/post.js
const state = {
post: [],
};
const getters = {
post: (state) => {
return post;
}
};
const actions = {
async fetchPost({ commit }, arg) {
try {
await axios.get("/post/" + arg.slug).then((response) => {
commit("setPost", response.data);
});
} catch (error) {
console.log(error);
}
},
};
const mutations = {
setPost: (state, post) => (state.post = post),
};
export default {
state,
getters,
actions,
mutations,
};
Your getter is utterly wrong: a state getter is supposed to be a function that takes in the entire state as a param and retrieves whatever you're interested in from it. Your version...
const getters = {
post: (state) => {
return post;
}
};
...takes in the state as a param but doesn't use it. Instead, it returns a variable (post) which has not been defined in that context.
Which will always return undefined, regardless of current value of state.post.
And, as you already know, JavaScript can't access property 'name' of undefined.
To get the current value of state.post, use:
const getters = {
post: state => state.post
}
Or
const getters = {
post: (state) => { return state.post; }
}
... if you fancy brackets.
Also, out of principle, I suggest initializing your post with an empty object {} instead of an empty array [].
Changing variable types as few times as possible is a very good coding habit, providing huge benefits in the long run.
Edit (after [mcve])
You have a bigger problem: the import from your axios plugin returns undefined. So you can't call get on it. Because you wrapped that call into a try/catch block, you don't get to see the error but the endpoint is never called.
I don't know where you picked that plugin syntax from but it's clearly not exporting axios. Replacing the import with import axios from 'axios' works as expected.
Another advice would be to namespace your store module. That's going to become useful when you'll have more than one module and you'll want to specifically reference a particular mutation/action on a specific module. You'll need to slightly change mapActions and mapGetters at that point.
See it working here.

want to show updated status value in another component

i want to watch when a mutation called and updated a status. i make a component to show database table count when api called.
this is my store i wrote
const state = {
opportunity: ""
}
const getters = {
countOpportunity: state => state.opportunity
}
const actions = {
// count opportunity
async totalOpportunity({ commit }) {
const response = await axios.get(count_opportunity)
commit("setOpportunity", response.data)
},
}
const mutations = {
setOpportunity: (state, value) => (state.opportunity = value)
}
i want to show this getter value when this mutation called in another component name Opportunity.vue file.
i showed database count values in file name Dashboard.vue
i wrote it like this.
computed: {
...mapGetters(["countOpportunity"])
},
watch: {},
mounted() {
//do something after mounting vue instance
this.$store.watch(() => {
this.$store.getters.countOpportunity;
});
},
created() {
this.totalOpportunity();
},
methods: {
...mapActions(["totalOpportunity"])
}
and showed my view like this.
<div class="inner">
<h3>{{ countOpportunity }}</h3>
<p>Opportunities</p>
</div>
when api called and count increase shows my mutations. but my view value not updated (countOpportunity). any one can help me to fix this.
The issue here (most likely) is that the value of response.data is an object or an array. You've initially defined opportunity as '' which is not an observable object or array. You have 2 choices:
Redefine it as an empty object or array, depending on the response:
opportunity: [] // or {}
Otherwise, use Vue.set() to apply reactivity when changing it:
(Vue.set(state, 'opportunity', value))

vue computed property not able to get data

I am currently experiencing an issue where the computed() property is not able to get data. Although data was already initiated in created() property. Am I doing it wrong? Please advise how I can fix this issue.
const randomPlayers = {
template:
`
<input type="text" v-model="search_player">
<div v-for="player in modPlayers" v-if="list_of_random_players!=null">
<p>{{player.firstname}}</p>
<p>{{player.lastname}}</p>
<div>
`,
props: ['data'],
data (){
return{
list_of_random_players: null,
search_player: null
}
},
created(){
this.get_random_players()
},
computed: {
modPlayers(){
return this.list_of_random_players.filter( person => {
return !this.search_player ||
( person.firstname.toLowerCase().indexOf(this.search_player.toLowerCase()) > -1 || person.lastname.toLowerCase().indexOf(this.search_player.toLowerCase()) > -1)
})
}
},
methods: {
get_random_players: function(){
$.post(
url:'random_url'
data: {
players: data
}
).done((success)=>{
this.list_of_random_players: JSON.parse(success)
})fail((err)=>{
console.log(err)
})
}
}
}
I get the following two errors:
(1) TypeError: Cannot read property 'filter' of null
(2) TypeError: this.list_of_random_players.filter is not a function
From Vue: "When a Vue instance is created, it adds all the properties found in its data object to Vue’s reactivity system. When the values of those properties change, the view will “react”, updating to match the new values."
So data is a function that returns an object but as mentioned by #Sovalina you are not returning it so you cannot access its properties. You need to add return and change null to []:
data() {
return {
list_of_random_players: [],
search_player: []
}
},
or you can do without return and like a regular object:
data: {
list_of_random_players: [],
search_player: []
}
When your Vue component is used multiple times, it is better to use it like a function(first case).
"When defining a component, data must be declared as a function that returns the initial data object. Why? Because there will be many instances created using the same definition. If we still use a plain object for data, that same object will be shared by reference across all instance created! By providing a data function, every time a new instance is created we can call it to return a fresh copy of the initial data."
Reference:link
It might be just a typo but you need to add : to methods as well.

Vue store dispatch single property instead whole object

I was wondering if it is possible, to dispatch only a single property to vuex store instead the whole object. There are no possibilities written in vuex docs. Currently I store object like this:
store.dispatch('currentUser', {
memberData: 'fooBar'
});
Some times I just want to fetch only a single value from database and push it into store. Is there a way to do that?
UPDATE
I think my question is unclear.
Actually I need to access a child nested property of memberData in dispatch, to change only one element of memberData. To be honest, it does not matter what response is. It could be 'foo' as well.
If you review the documentation for dispatch, the 2nd argument payload, can be any type. It doesn't necessarily need to be an object-style dispatch nested in a property:
Dispatch:
store.dispatch('currentUser', response[0]);
Store:
state: {
currentUser: undefined
},
mutations: {
setCurrentUser(state, currentUser) {
state.currentUser = currentUser;
}
},
actions: {
currentUser(context, payload) {
context.commit('setCurrentUser', payload);
}
}
Mutation:
setCurrentUser(state, currentUser) {
state.currentUser = currentUser;
}
Here is a example in action.
Update:
If the goal instead is to merge/update changes, you can use spread in object literals. This is also mentioned in the Vuex documentation for Mutations Follow Vue's Reactivity Rules.
Dispatch:
store.dispatch('currentUser', { systemLanguage: response[0].systemLangId });
Store:
state: {
memberData: { systemLanguage: 'foo' }
},
mutations: {
updateCurrentUser(state, updates) {
state.memberData = { ...state.memberData, ...updates };
}
},
actions: {
currentUser(context, payload) {
context.commit('updateCurrentUser', payload);
}
}
Here is an example of that in action.
Hopefully that helps!

Categories

Resources