Reputation: 468
I am trying to create a simple with vue-cli and the router that fetches Covid-19 cases by Country from a JSON object of arrays. This is my first Vue app. However, I keep getting an error about "Declaring Reactive Properties". I searched dozens of similar errors on many different forums and seemed to do the trick.
Most of the code is from vue.org, except for the JSON link.
Api.js:
import axios from "axios";
import Vue from "vue";
new Vue({
el: "#app",
data() {
return {
info: null,
loading: true,
errored: false
};
},
template: "<div>{{ output.info }}</div>",
mounted() {
axios
.get("https://pomber.github.io/covid19/timeseries.json")
.then(response => {
this.info = response.data;
console.log(this.info);
})
.catch(error => {
console.log(error);
this.errored = true;
})
.finally(() => (this.loading = false));
}
});
export default {
name: "About",
props: {
loading: String,
errored: String,
info: String
}
};
About.js
<template>
<h1>Covid-19 cases by Country</h1>
<section v-if="errored">
<p>
We're sorry, we're not able to retrieve this information at the moment,
please try back later
</p>
</section>
<section v-else>
<div v-if="loading">Loading...</div>
<div v-else v-for="data in info" :key="data" class="currency">
<h1>{{ data.Portugal[0].deaths }}</h1>
</div>
</section>
Error:
[Vue warn]: Property or method "errored" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property
I can see the warning 3 times, for each of the props errored, loading and info, the most important one.
Upvotes: 1
Views: 626
Reputation: 90068
There's a bit of confusion in what you have.
In Api.js
you're mounting a Vue app without much of a template to an element with an id of app
. And then you export a Vue-like object which, if imported in another component could be used like <about />
. However, we don't know if you use it anywhere else.
In About.js
you seem to only have a <template>
, without controller or style. You probably wanted to couple the two together, which would look similar to this (I can't use SFC's on SO, so I just declared the component inline, with Vue.component()
):
Vue.config.productionTip = false;
Vue.config.devtools = false;
Vue.component('About', {
template: `<div>
<h1>Covid-19 cases by Country</h1>
<section v-if="errored">
<p>
We're sorry, we're not able to retrieve this information at the moment,
please try back later
</p>
</section>
<section v-else>
<div v-if="loading">Loading...</div>
<div v-else v-for="(data, name) in info" :key="name" class="currency">
<h1>{{ name }}</h1>
<div v-for="(entry, key) in data" :key="key">{{entry}}</div>
</div>
</section>
</div>`,
data: () => ({
info: null,
loading: true,
errored: false
}),
mounted() {
axios
.get("https://pomber.github.io/covid19/timeseries.json")
.then(response => {
this.info = response.data;
// console.log(this.info);
})
.catch(error => {
// console.log(error);
this.errored = true;
})
.finally(() => (this.loading = false));
}
})
new Vue({
el: '#app'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<div id="app">
<About/>
</div>
If you want to do the loading of data in parent, you have to pass the required props to <About />
, along these lines:
In App.js
template:
<About :loading="loading"
:info="info"
:errored="errored"
/>
In About.js
s props:
props: {
loading: Boolean,
info: Object,
errored: Boolean
}
That's the gist of it. But, in your case, that would seem an unnecessary complication.
As a side note, to speed things up towards your end goal, I took the liberty to add a few more features to your code: https://codesandbox.io/s/compassionate-dan-6z3zo
I hope you'll find them helpful.
Upvotes: 2