I’m showing the data parameters (name, height, mass…) for a character using the swapi (https://swapi.co/), AXIOS and VUE.
I already have the url for a character (i.e http://localhost:8081/person/1) and it to match with the swapi API (https://swapi.co/api/people/1/), but I don’t know where is my error
I’m using Axios and Vue, I’ve made a service for the Axios get request and the method to get the information in my vue.js file.
The code for my “people.service.js” service is this:
import axios from “axios”;
const PeopleService = {};
// PeoplesService.getPeoples = async () => {}; - Para sacar el listado de planetas con un v-for
PeopleService.getPeople = async id => {
try {
const result = await axios.get(`people/${id}`);
// For getting the species
const specieRoute = result.data.species[0].split(“/“);
const idSpecie = specieRoute[specieRoute.length - 2];
const especie = await axios.get(`species/${idSpecie}`);
// For getting the planets
const planetRoute = result.data.homeworld.split(“/“);
const idPlanet = planetRoute[planetRoute.length - 2];
const planeta = await axios.get(`planets/${idPlanet}`);
// console logs to show results
console.log(result.data);
console.log(idSpecie);
console.log(especie.data);
console.log(planeta.data);
// data information
const people = {
nombre: result.data.name,
altura: result.data.height,
peso: result.data.mass,
genero: result.data.gender,
piel: result.data.skin_color,
especie: especie.data.name, // Lo saco del servicio de especies
planeta: planeta.data.name // Lo saco del servicio de planetas
};
return people;
} catch (error) {
const errorStatus = error.response.status;
let errorMessage = “”;
if (errorStatus === 404) {
errorMessage = “No se encontr al personaje”;
} else {
errorMessage = “Ocurri un error”;
}
throw new Error(errorMessage);
}
};
export default PeopleService;
And my vue.js file is:
<template>
<div>
The id is { $route.params.id }, and the name is { people.nombre }
</div>
</template>
<script>
import PeopleService from “@/services/people.service”;
export default {
async create() {
this.userId = this.$route.params.id;
this.getUser();
},
data() {
return {
user: null,
loading: false,
error: null,
userId: this.$route.params.id
};
},
methods: {
async getUser() {
try {
this.loading = true;
this.people = null;
this.error = null;
this.people = await PeopleService.getPeople(this.userId);
} catch (error) {
this.error = error.message;
} finally {
this.userId = null;
this.loading = false;
}
}
}
};
</script>
<style lang=”scss” scoped></style>
I expect the result to be the name of the character, but i get “[vue.js warn]: Error in render: “TypeError: Cannot read property ‘nombre’ of undefined”
Solution :
when creating a second answer in order to outline how you could do this using vue-router, since you were asking about it.
Disclaimer: this isn’t the ‘cleanest’ code - this pseudo code is designed to loosely illustrate the objective.
Hope this helps!
CodePen mirror
const PeopleService = {};
PeopleService.getPeople = async id => {
try {
const result = await axios.get(`https://swapi.co/api/people/${id}\`);
const specieRoute = result.data.species[0].split(“/“);
const idSpecie = specieRoute[specieRoute.length - 2];
const especie = await axios.get(`https://swapi.co/api/species/${idSpecie}\`);
const planetRoute = result.data.homeworld.split(“/“);
const idPlanet = planetRoute[planetRoute.length - 2];
const planeta = await axios.get(`https://swapi.co/api/planets/${idPlanet}\`);
const people = {
nombre: result.data.name,
altura: result.data.height,
peso: result.data.mass,
genero: result.data.gender,
piel: result.data.skin_color,
especie: especie.data.name, // Lo saco del servicio de especies
planeta: planeta.data.name // Lo saco del servicio de planetas
};
return people;
} catch (error) {
const errorStatus = error.response.status;
let errorMessage = “”;
if (errorStatus === 404) {
errorMessage = “No se encontr al personaje”;
} else {
errorMessage = “Ocurri un error”;
}
throw new Error(errorMessage);
}
};
const peopleComponent = {
name: ‘people’,
template: “#peopleComponent”,
data() {
return {
userId: null,
peopleArray: [],
peopleObject: null,
error: null
};
},
mounted() {
this.userId = this.$route.params.id;
this.getUser();
},
methods: {
async getUser() {
try {
let person = await PeopleService.getPeople(this.userId);
this.peopleArray.push(person); // add to array
this.peopleObject = person; // assign to object
} catch (error) {
this.error = error.message;
}
}
}
};
const homeComponent = {
name: ‘home’,
template: “#homeComponent”,
}
const routes = [
{ path: ‘’, name: ‘home’, component: homeComponent },
{ path: ‘/people/:id’, name: ‘people’, component: peopleComponent },
]
const router = new VueRouter({ routes });
new Vue({
router
}).$mount(‘#app’);
.nav-links {
background-color: lightgray;
text-align: center;
}
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.4/vue-router.min.js"></script>
<script src=”https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<div id=”app”>
<div>
<router-view></router-view>
</div>
</div>
<script type=”text/x-template” id=”homeComponent”>
<div>
<hr/>
<div class=”nav-links”>
<h2>Home</h2>
<div>
<router-link :to=”{ name: ‘people’, params: { id: 1 } }”>Person 1</router-link>
<br/>
<router-link :to=”{ name: ‘people’, params: { id: 2 } }”>Person 2</router-link>
</div>
</div>
<hr/><br/>
</div>
</script>
<script type=”text/x-template” id=”peopleComponent”>
<div>
<hr/>
<div class=”nav-links”>
<h2>People</h2>
<div>
<router-link :to=”{ name: ‘home’ }”>Home</router-link>
</div>
</div>
<hr/><br/>
<h3>People as ARRAY</h3>
<div v-if=”peopleArray.length > 0”>
<div v-for=”(p, index) in peopleArray” :key=”index”>
<div><b>nombre:</b> { p.nombre }</div>
<div><b>altura:</b> { p.altura }</div>
<div><b>peso:</b> { p.peso }</div>
<div><b>genero:</b> { p.genero }</div>
<div><b>piel:</b> { p.piel }</div>
<div><b>especie:</b> { p.especie }</div>
<div><b>planeta:</b> { p.planeta }</div>
</div>
</div>
<div v-else>
<i>Loading People…</i>
</div>
<br/>
<hr/> — OR —
<hr/><br/>
<h3>People as OBJECT</h3>
<div v-if=”peopleObject != null”>
<div v-for=”(p, index) in peopleObject” :key=”index”>
{ p }
</div>
</div>
<div v-else>
<i>Loading People…</i>
</div>
</div>
</script>
Solution 2:
Edit: it doesn’t appear you have a data.people property set up before assigning a value to it.. Can you try to add a people property under data and try again?
…
data() {
return {
…
people: null,
…
}
}
…
First and foremost, it is not very clear how you are actually sending requests to swapi.. how are you doing this?
I wrote a modified version of what you’re trying to accomplish using the code, but with the swapi URL.. if you change the code to use the swapi URL instead of localhost, does it work?
CodePen mirror
Code snippet is also available below
Edit: CodePen with routing example - detailed secondary answer has also been posted..
If you’re proxying requests locally
What does the server side configuration look like? Are you using node or something else? How are you actually sending API requests to swapi?
If you’re using a local database
Does the local database have any data in it? You may need to set up a service that pulls down data from the swapi API and saves it to the local database, before trying to query the local database for data.
when also not using any routing, so there could be an issue with the routes? At any rate, I hope this helps:
/**
* People service
*/
const PeopleService = {};
PeopleService.getPeople = async id => {
try {
const result = await axios.get(`https://swapi.co/api/people/${id}\`);
const specieRoute = result.data.species[0].split(“/“);
const idSpecie = specieRoute[specieRoute.length - 2];
const especie = await axios.get(`https://swapi.co/api/species/${idSpecie}\`);
const planetRoute = result.data.homeworld.split(“/“);
const idPlanet = planetRoute[planetRoute.length - 2];
const planeta = await axios.get(`https://swapi.co/api/planets/${idPlanet}\`);
const people = {
nombre: result.data.name,
altura: result.data.height,
peso: result.data.mass,
genero: result.data.gender,
piel: result.data.skin_color,
especie: especie.data.name,
planeta: planeta.data.name
};
return people;
} catch (error) {
const errorStatus = error.response.status;
let errorMessage = “”;
if (errorStatus === 404) {
errorMessage = “No se encontr al personaje”;
} else {
errorMessage = “Ocurri un error”;
}
throw new Error(errorMessage);
}
};
/**
* vue.js app
*/
new Vue({
el: “#app”,
data: {
userId: 1,
peopleArray: [],
peopleObject: null,
error: null
},
mounted() {
this.getUser();
},
methods: {
async getUser() {
try {
let person = await PeopleService.getPeople(this.userId);
this.peopleArray.push(person); // add to array
this.peopleObject = person; // assign to object
} catch (error) {
this.error = error.message;
}
}
}
});
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src=”https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<div id=”app”>
<h3>People as ARRAY</h3>
<div v-if=”peopleArray.length > 0”>
<div v-for=”(p, index) in peopleArray” :key=”index”>
<div><b>nombre:</b> { p.nombre }</div>
<div><b>altura:</b> { p.altura }</div>
<div><b>peso:</b> { p.peso }</div>
<div><b>genero:</b> { p.genero }</div>
<div><b>piel:</b> { p.piel }</div>
<div><b>especie:</b> { p.especie }</div>
<div><b>planeta:</b> { p.planeta }</div>
</div>
</div>
<div v-else>
<i>Loading People…</i>
</div>
<br/><hr/> — OR — <hr/><br/>
<h3>People as OBJECT</h3>
<div v-if=”peopleObject != null”>
<div v-for=”(p, index) in peopleObject” :key=”index”>
{ p }
</div>
</div>
<div v-else>
<i>Loading People…</i>
</div>
</div>
Solution 3:
The correct code for the vue.js file is:
<template>
<div>
<h3>Modo array</h3>
<div v-if=”peopleArray.length > 0”> // Detecta que el id es mayor que 0
<div v-for=”(p, index) in peopleArray” :key=”index”>
<div><b>nombre:</b> { p.nombre }</div>
<div><b>altura:</b> { p.altura }</div>
<div><b>peso:</b> { p.peso }</div>
<div><b>genero:</b> { p.genero }</div>
<div><b>piel:</b> { p.piel }</div>
<div><b>especie:</b> { p.especie }</div>
<div><b>planeta:</b> { p.planeta }</div>
</div>
</div>
<div v-else>
<i>Loading People…</i>
</div>
<br/><hr/> — <hr/><br/>
<h3>Modo objeto</h3>
<div v-if=”peopleObject != null”>
<div v-for=”(p, index) in peopleObject” :key=”index”>
{ p }
</div>
</div>
<div v-else>
<i>Loading People…</i>
</div>
</div>
</template>
<script>
import PeopleService from “@/services/people.service”;
export default {
data() {
return {
userId: null,
loading: false,
peopleArray: [], // Para obtener los valores como array
peopleObject: null, // Para que los valores que devuelva sean como array o como objeto
error: null
};
},
mounted() {
this.userId = this.$route.params.id; // el userId corresponde con el ltimo nmero de la url
this.getUser();
},
methods: {
async getUser() {
try {
this.loading = true;
this.people = null;
this.error = null;
let person = await PeopleService.getPeople(this.userId); // Hace la peticin sobre el userID
this.peopleArray.push(person); // Aadir al array
this.peopleObject = person; // Asignar a objeto
} catch (error) {
this.error = error.message;
} finally {
this.userId = null;
this.loading = false;
}
}
}
};
</script>
<style lang=”scss” scoped></style>