Home > OS >  Vue.js getting null for the json when initially loading
Vue.js getting null for the json when initially loading

Time:10-19

I am learning vue.js and trying to call a json file and parse the data. Everything is working but when I refresh the page, I see a blank page before my data is loaded and in console log I get TypeError: e.myData is null. After few second the data is displayed on the page.

main.js:

new Vue({
    el: `#app`,
    render: h => h(App,{
      props:{
        todoID: this.dataset.id
      }
    })
  })

and my App.vue:

<template>
  <div>
      <div>{{myData.getName()}}</div>
  </div>
</template>

<script>
import Info from '@/getInfo'
export default {
  name: 'App',
  props: {
    todoID: String,
  },
  data() {
    return {
      data: null,
      myData: null
    }
  },
  created() {
    fetch(`http://localhost/json-end-point/`)
      .then(async response => {
        const data = await response.json();

        if (!response.ok) {
          const error = (data && data.message) || response.statusText;
          return Promise.reject(error);
        }

        // set the date here, am I doing this right?
        this.myData = new Info(data);
        this.data = data;
      })
      .catch(error => {
        this.errorMessage = error;
        console.error("There was an error!", error);
      });
  }
}
</script>

getInfo.js

export default class Info {
    constructor(Data) {
      if (Data) {
        const data = JSON.parse(Data);
        console.log(data.name); // returns name
        // console.log(data);   // returns the json data
        this.name = data.name;
      }
    }
    
    getName() {
      return this.name;
    }
}

I think I am doing something wrong here this.myData = new Info(data); but I am not sure what I can do.

Update

I was able to remove the console log by adding v-if="myData !== null". Still not sure assigning data like this this.myData = new Info(data); is a good approach. How can I improve this code?

CodePudding user response:

Here's an example of how to let the template show different states so it doesn't try to render the data before it arrives, but shows a loading indicator instead.

<template>
  <div v-if="myData">
      <div>{{ myData.getName() }}</div>
  </div>
  <div v-else-if="isLoading">
    Loading data...
  </div>
  <div v-else-if="errorMessage">
    {{ error.message }}
  </div>
</template>

<script>
import Info from '@/getInfo'
export default {
  name: 'App',
  props: {
    todoID: String,
  },
  data() {
    return {
      data: null,
      myData: null,
      error: null
    }
  },
  async created() {
    await this.getData()
  },

  methods: {
    async getData() {
      try {
        const response = await fetch(`http://localhost/json-end-point/`)

        if (!response.ok) {
          throw new Error(data?.message || response.statusText)
        }

        this.data = await response.json();
        this.myData = new Info(this.data);
      } catch (error) {
          this.error = error;
          console.error("There was an error!", error);
      }
    }
  }
}
</script>

CodePudding user response:

You could stick the myData.getName() call inside a computed field that either returns the name if myData != null or an empty string (or whatever value you want when there is no data available).

Something like this

computed: {
    getName() {
        return this.myData ? this.myData.getName() : '';
    }
}
  • Related