Home » vue » vue.js not all of the data is passed

vue.js not all of the data is passed

Posted by: admin November 26, 2021 Leave a comment

Questions:

Good evening, I am retrieving data with axios and when I console log it, I see that it has been retrieved successfully. When I pass that data to my component, the data is somehow not full. It just shows the data that was retrieved from first axios.get ( conversations but no messages ), but when I check it with vue.js debugging tools I can see that the object has ALL the data from server. Dont know where it goes wrong.

app.js

 const app = new Vue({
    el: '#app',
    data: {
        conversations: {
            list: [],
            current: {
                messages: []
            }
        }
    },
    created() {
        axios.get('/conversations').then(response => {
            this.conversations.current = response.data[0];
        });

        axios.get('/messages').then(response => {
            this.conversations.current.messages = response.data;
            console.log(this.conversations.current);
            /* this console.log prints the json with 25 messages in it */
        });
    }
});

index.blade.php

<div class="list-group">
   <div class="list-group-item active">Messages</div>
   <chat-log :conversations="conversations"></chat-log>
</div>

chat-log.vue

<template lang="html">
    <div class="chat-log pre-scrollable">
        <chat-message class="list-group-item" v-for="message in conversations.current.messages" :message="message"></chat-message>

        {{ conversations.current.messages }} // THIS IS EMPTY SOMEHOW
    </div>
</template>

<script>
    export default {
        props: ['conversations']
    }
</script>

In chat-message component I created a method that is called on click to retrieve messages again and put them in array again and then they somehow appear but I dont understand why they do not appear on load.

Answers:

You have no guarantee that those asynchronous calls will return in order unless used with a Promise:

Promise.all([
    axios.get('/conversations'),
    axios.get('/messages')
]).then(values => {
    this.conversations.current = values[0]
    this.conversations.current.messages = values[1]
})

Promise.all()

Promise.all waits for all fulfillments (or the first rejection)

Also, your data property is not reactive. It must be declared as a function:

data () {
    return {
        conversations: {
            list: [],
            current: {
                messages: []
            }
        }
    }
}

###

There’s no guarantee that your ‘conversations’ endpoint is going to resolve before the ‘messages’ endpoint. Try structuring it in a promise chain or, as @btl suggested, using promise.all().

new Vue({
    el: '#app',
    data: function() {
        return {
            conversations: {
                list: [],
                current: {
                    messages: []
                }
            }
        }
    },
    created() {
        return Promise.all([
            axios.get('/conversations'),
            axios.get('/messages')
        ])
        .then(reply => {
            this.conversations.current = reply.data[0];
            this.conversations.current.messages = reply.data[1];
        });
    }
});