I am doing a React.js
project. I am fetching data from an API with different endpoints. I have a component where I pass data from an endpoint of this API by props from its parent. Also, on that component I am calling the rest of the endpoints. I want to be able to use all the values that match the props (first API call). The issue is that the first API call includes the values of the other endpoints, but only the url. So I did a function lastNumber
(that doesn't work) in order to let both values match. Also, that function needs to be able to call number with more than one digit and I do not know how to do it. For instance, the las character of the string of those url could be 1,2 or 10, 12,20 etc. So, I need to be able to use the "people number". Maybe there is a different approach. This is the whole component:
import { useEffect, useState } from "react";
import styles from './MovieDetail.module.css';
const MovieDetail = ({films}) => {
const [results, setResults] = useState([]);
const urls = {
people: "https://www.swapi.tech/api/people/",
planets: "https://www.swapi.tech/api/planets/",
starships: "https://www.swapi.tech/api/starships/",
vehicles: "https://www.swapi.tech/api/vehicles/",
species: "https://www.swapi.tech/api/species/"
}
const fetchApis = async () => {
try {
const responses = await Promise.all(Object.entries(urls).map(async ([ key, url ]) => {
const res = await fetch(url)
return [ key, (await res.json()).results ]
}))
return Object.fromEntries(responses)
} catch (err) {
console.error(err)
}
}
useEffect(() => {
fetchApis().then(setResults)
}, [])
console.log('results', results)
const lastNumber = Number(films.properties.characters.slice(-1) - 1);
return (
<div className={styles.card}>
<div className={styles.container}>
<h2>{films.properties?.title}</h2>
<p>{films.description}</p>
<p>Release date: {films.properties?.release_date}</p>
<p>Director: {films.properties?.director}</p>
<p>Producer: {films.properties?.producer}</p>
<p>Characters: {films.properties?.producer}</p>
<p>Characters:</p>
{results.people[lastNumber].map(result => (
<ul>
<li>{result.properties.name}</li>
</ul>
))}
</div>
</div>
);
}
export default MovieDetail;
This is a sandbox link with the whole code.
A more practical explanation: In the API there are films, and in every one there is a list of characters (people) that worked on the movie. So, I would like to render the movie title, director etc and the list of characters that worked on the movie.
In MovieDetail
, you are getting a film
object, not an array of films? So you should start by renaming it film
, so it is clearer that it is an object, not an array.
Then, you know that the film
contains some information that you want, for instance the people that played in it. So you have to fetch their URLs, like this:
const peoples = film.properties.characters.map(characterURL => {
// fetch the people through an API call
const people = (await (await fetch(characterURL)).json()).results
return people
}
Then, in peoples, you have every people that played in the movie. So if you want to display a list of characters name, you can do like this:
{peoples.map(people=> (
<ul>
<li>{people.properties.name}</li>
</ul>
))}
Does it answer your question ?