Reputation: 299
i am new in Vue Js. I am doing an TODO web application. I took firebase as a backend and database. I am using Vuex for the state management. Until now i am able to add data to firebase, but when come time to read, i am stuck. i couldn't read data from firebase. It's show an empty array in component from where i am calling.
import Vue from 'vue';
import Vuex from 'vuex';
import firebase from "firebase";
Vue.use(Vuex);
export const store = new Vuex.Store({
state:{
events:[],
error:''
},
mutations:{
setEvent(state){
let items = [];
firebase.database().ref('eventos')
.on('value',event =>{
event.forEach(data =>{
items.push(data.val())
})
});
state.events = items
},
setError(state, payload) {
state.error = payload;
},
},
actions:{
addEvent(context,payload){
firebase.database().ref('eventos/').push(payload)
.then((event)=>{
context.commit('setEvent',event)
}).catch(err =>{
console.log(err)
})
},
},
getters:{
eventList: state => {
return state.events
}
}
});
In this component i am calling the array events to show all value
<template>
<div>
{{eventList}}
</div>
</template>
<script>
export default {
name: "ReadEvents",
computed:{
eventList(){
return this.$store.getters.eventList;
}
}
}
Upvotes: 0
Views: 2454
Reputation: 76
For a start, you shouldn't try to execute any asynchronous code in vuex mutations, see https://vuex.vuejs.org/guide/mutations.html#mutations-must-be-synchronous
Instead, include the logic in your action, and only call the mutation when you have the data that you want to commit to the state. Something like this:
export const store = new Vuex.Store({
state: {
events: [],
error: ''
},
mutations: {
setEvents (state, events) {
state.events = events;
},
setError (state, payload) {
state.error = payload;
}
},
actions: {
addEvent ({ commit }, event) {
firebase.database().ref('eventos').push(event)
.then(() => {
firebase.database().ref('eventos')
.on('value', data => {
const events = data.map(item => {
return { "$id": item.id, ...item.val() };
});
commit('setEvents', events);
});
})
.catch(err => {
console.log(err);
})
},
},
getters:{
eventList: state => {
return state.events;
}
}
});
Upvotes: 0
Reputation: 599956
Data is loaded from Firebase asynchronously. While this is going on, your main code continues to run, so that the UI isn't blocked. Then once the data is available, your callback is invoked with that data.
It's easiest to see this by placing some log statements:
setEvent(state){
console.log("Before starting to load data");
firebase.database().ref('eventos')
.on('value',event =>{
console.log("Got data");
});
console.log("After starting to load data");
},
When you run this code, it logs:
Before starting to load data
After starting to load data
Got data
While this probably wasn't what you expected, it completely explains why your data isn't showing up. By the time you call setState
, the items
hasn't been populated yet.
To solve this problem, move your setState
call into the on()
callback:
setEvent(state){
firebase.database().ref('eventos')
.on('value',event =>{
let items = [];
event.forEach(data =>{
items.push(data.val())
})
state.events = items
});
},
Unrelated to the current problem, I highly recommend also storing data.key
in your array, as you're bound to need it down the line when you need to find an item from the array in the database.
The code for that could be for example:
event.forEach(data =>{
items.push({ "$id": data.key, ...data.val() })
})
So with this, the key is stored in $id
, while all the other properties are copied as is.
Upvotes: 2