Mohamed Mamun
Mohamed Mamun

Reputation: 299

Read data from firebase in vuex

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.

this is where i am showing the value of array This is my store.js

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

Answers (2)

Paul Renshaw
Paul Renshaw

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

Frank van Puffelen
Frank van Puffelen

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

Related Questions