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