Vue JS returns [__ob__: Observer] data instead of my array of objects

I've created a page where I want to get all my data from the database with an API call, but I'm kinda new to VueJS and Javascript aswell and I don't know where I'm getting it wrong. I did test it with Postman and I get the correct JSON back.

This is what I get:

[__ob__: Observer]
length: 0
__ob__: Observer {value: Array(0), dep: Dep, vmCount: 0}
__proto__: Array

This is what I want:

(140) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, …]
[0 … 99]
[100 … 139]
length: 140
__ob__: Observer {value: Array(140), dep: Dep, vmCount: 0}
__proto__: Array

Thats my Vue template file:

<template>
    <div>
        <h2>Pigeons in the racing loft</h2>
        <div class="card-content m-b-20" v-for="pigeon in pigeons" v-bind:key="pigeon.id">
            <h3>{{ pigeon.id }}</h3>
        </div>
    </div>
</template>

<script>
export default {
    data(){
        return{
            pigeons: [],
            pigeon: {
                id: '',
                sex: '',
                color_id: '',
                pattern_id: '',
                user_id: '',
                loft_id: '',
                country: '',
                experience: '',
                form: '',
                fatique: ''
            },
            pigeon_id: ''
        }
    },
    created(){
        this.fetchPigeons();
        console.log(this.pigeons); // Here I got the observer data instead my array
    },

    methods: {
        fetchPigeons(){
            fetch('api/racingloft')
            .then(res => res.json())
            .then(res => {
                console.log(res.data); // Here I get what I need
                this.pigeons = res.data;
            })
        }
    }
}
</script>

I've tried to do it with axios aswell, but it gave me exactly the same thing. When I console it from the method it gives my data, but outside it just gives nothing.


Solution 1:

Can also try this:

var parsedobj = JSON.parse(JSON.stringify(obj))
console.log(parsedobj)

It was brought by Evan You himself here and more info on that here

But waiting for the answer is a first step.

Solution 2:

This happens because Vue js convert every item in the data to something that can be observed. So it makes sense if you console log something in the data. The output will be something wrapped into an observer.

To have a better vision on your data I suggest you to install the Vue dev tools. https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en

Solution 3:

Here is my solution:

add new method something like log to your $root component. App.vue's created is recommended:

this.$root.log = function log() {
  for (let i = 0; i < arguments.length; i += 1) {
    if (typeof (arguments[i]) === 'object') {
      try {
        arguments[i] = JSON.parse(JSON.stringify(arguments[i]));
      } catch (e) {
        console.error(e);
      }
    }
  }
  console.log(...arguments);
};

just call this.$root.log(this.pigeons) in your component.

My result:

BEFORE:

enter image description here

AFTER:

enter image description here

Solution 4:

You should probably wait for the fetch to finish then console.log the result ..

created(){
    this.fetchPigeons().then(() => console.log(this.pigeons));
},

The way you were doing it you were logging the result synchronously so it gets executed before the fetch is done.

Edit: Also as @barbsan pointed out in his comment below your fetchPigeons needs to return a promise for then to work. fetch returns a promise so you just need to return fetch in fetchPigeons

fetchPigeons(){
    return fetch('api/racingloft')
    .then(res => res.json())
    .then(res => {
        console.log(res.data); // Here I get what I need
        this.pigeons = res.data;
    })
}

Solution 5:

Basically, what you've done is that the function fetches the pigeon array, but as its running in parallel, you called the console.log. Easy fix:

this.fetchPigeons().then(()=>{
  console.log(this.pigeons);
}