140

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.

3
  • try to replace the console.log in the created function by Commented Oct 18, 2018 at 12:08
  • 4
    You're trying to log the data in created() before the asynchronous fetch completes, so it's still empty (except for the Observable that Vue uses to detect changes in the data, such as when the fetch completes, so it can re-render the component.) Commented Oct 18, 2018 at 20:13
  • So, what was the problem? Catched same bug today Commented Dec 24, 2021 at 8:33

16 Answers 16

115

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.

Sign up to request clarification or add additional context in comments.

3 Comments

why doesnt this help me and one who asked the problem, solve the problem? i tried all of the asnwer from below except stackoverflow.com/a/56013942/5057913. how couldnt figuer out where to keep the code. i get empty array when i use teh above code when i do have array sfull of value on that observer
This fixed my problem, thank you.
would like to explain that this method will make a copy, while var parsedobj = [...obj] could pass by reference if using a deeply nested array. see here
15

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

2 Comments

Yes thanks. I use Vue dev tools. But when I use it I only see <Root> =$vm0, nothing else even if I click on it.
Are you looking at the good component? Could you add a screenshot of what you see in the dev tools. It will help to figure out what is going on.
10

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

Comments

6

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;
    })
}

12 Comments

[Vue warn]: Error in created hook: "TypeError: Cannot read property 'then' of undefined" found in ---> <Pigeons> at resources/js/components/Pigeons.vue <Root> I get this one. Neither the console, nor the rendering shows me that I have objects.
@HusamIbrahim fetchPigeons doesn't return promise, you need also to add return before fetch
@barbsan Thanks for pointing that out. I missed that part. +1
Actually return fixed the issue, but I still can't render it to the page. i dont know what the problem is. Im following youtube video series, and it just works without the return aswell. I don't know what I set up incorrectly. It also shows them info about the Vuejs datas in vue dev tools, while I only see <root> = $vm0 and nothing else even if I click on it.
The problem must be easy to solve because if I set up a message variable and set it up as {{message}}, it does show up in the page. But If I just modify data with created or mounted I just get back an empty array, thats why I doesnt render anything.
|
4

The best way possible

obj2 = JSON.stringify(obj)
obj3 = JSON.parse(obj2)

Or

obj2 = Object.assign([], obj)

It was brought by Evan You himself here and more info

Comments

2

You can use v-if directive to render the component once the data is there.

<h3 v-if="pigeons.length > 0">{{ pigeon.id }}</h3>

Comments

2

As mentioned by Husam Ibrahim, you should wait the async fetch() function to resolve. Another approach could be use async/await in your function:

methods: {
    async fetchPigeons(){
        await fetch('api/racingloft')
               .then(res => res.json())
               .then(res => {
                   console.log(res.data);
                   this.pigeons = res.data;
               })
    }
}

And then it should work:

<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>

2 Comments

Can we use standard promises instead of await?
For sure, but you will have to handle the promise resolution in another function maybe.
2

Thank you for all your suggestion. Things worked on my end by just using "const".

const cookieInfo = ToolCookieService.getToolNumbersFromCookie();

Thanks, Ranjit

Comments

2

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);
}

1 Comment

code doesnt work
1

I got the same problem still stuck ...

Wrote these according to Evan(Vue Author) JSON.parse(JSON.stringify(res.data)) method, But why can't normal data?

  methods: {
    async getdata() {
      console.log(1);
      await axios.get(API).then((res) => {
          console.log(2);
          if (!this.dataList.length) {
            this.dataList = JSON.parse(JSON.stringify(res.data));
            console.log(3);
            console.log(res.data, 'res.data ');
            console.log(this.dataList, 'this.dataList')
            console.log('----------check-----------',JSON.parse(JSON.stringify(res.data)));
          }
        })
        .catch(err => {
          console.error('failed: ' + err);
        })
      console.log(4);
    },

Comments

0

If you're returning an object instead an array and it has defined key props:

data () {
  return {
    object: {
      definedKey: [],
      anotherDefinedKey: []
    }
  }
}

Try check if the keys returned by your fetch are the same defined in your object, if you don't fulfill your object defined keys Vue will assume that you're still waiting for them.

Comments

0

If your goal is debugging WHAT included in Observer Vue instance, this is my solution:

Print out that variable in template block belongs to your Component

After that, you can reformat the structure of the output to observe the detail.

For example:

<template>
  <div>
    {{ pigeons }}
  <div>
</template>

Another way, if you wanna see it in console, you should put the console.log into mounted phase. Because at created phase, the this.pigeons still be empty. Ref: https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

Hope this helpful.

Comments

0

this is a good question. I do face the same issue, this should be due to the before and after of the async returns which created two object id.

may solved by splitting into two functions instead of complete in one single function

created(){
    this.fetchPigeons();
    console.log(this.pigeons); // Here I got the observer data instead my array
},

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


}

1 Comment

This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. To get notified when this question gets new answers, you can follow this question. Once you have enough reputation, you can also add a bounty to draw more attention to this question. - From Review
0

Destructuring the data works:

console.log({...obj})

Comments

0

this.pigeons = {...res.data};

This might sold the issue.

1 Comment

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
-4

Well I had exactly same problem but I solved it:

Just move app.js external link to head tag.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.