0

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?

5
  • 2
    you can add a v-if in the template to show it if the variable isn't null. right now the page renders before the call is finished Commented Oct 17, 2021 at 22:35
  • thanks doing v-if="myData !== null" removed the console log. Is doing this.myData = new Info(data); a good approach? or I should try another way? I dont want to learn the wrong way. Commented Oct 17, 2021 at 22:39
  • using new means you can't return a promise and wait, a better approach would be to wrap the fetching in an async function Commented Oct 18, 2021 at 10:35
  • @KareemKamal do you have an example? Commented Oct 18, 2021 at 13:04
  • yes, added an answer with an example Commented Oct 18, 2021 at 13:26

2 Answers 2

1

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>
Sign up to request clarification or add additional context in comments.

10 Comments

this returns an error Module build failed, reserved word 'await' for this line this.myData = await getData()
forgot the this. before getData, try with it
thanks, still the same error
added async to the created hook, sorry I'm too used to the linter doing these for me.
found it! the function returns undefined and we assign undefined to myData in created(), removing the assignment fixes it
|
0

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() : '';
    }
}

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.