reactjs - De ce nu pot să setez un array la datele API folosind useState()?
Deci, am o aplicație care folosește API-ul de Filme. Fac o cerere API, apoi transmit aceste date într-un array folosind hook-ul useState, practic codul meu arată astfel:
const App = () => {
type MovieType = { //declaring type
rate: string,
title: string,
tagline: string,
date: string,
};
interface MovieProps { //extending an interface with MovieType
movies: MovieType[],
}
const [movies, setMovies] = useState<MovieType[]>([]); //useState for setting an array to data from api
useEffect(() =>{
fetchMovies();
}, [])
async function fetchMovies() { //function for fetching movies
try{
let apikey = '{api_key}';
let url: string = 'https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=';
url = url + apikey;
const response = await axios.get<[MovieType]>(url);
setMovies(response.data);
}catch(e){
alert('Error');
}
}
return (
<div className="App">
<Header/>
<Hero movies={movies}/>
</div>
);
}
Deci practic, când rulez aplicația, primesc un alert cu o eroare. Am încercat să redenumesc useState, astfel încât să fie diferit de props în componenta <Hero>, și apoi am putut să trec datele într-un array. Dar când fac asta cu [movies, setMovies] nu funcționează. Așadar, presupun că problema este undeva la transmiterea props sau type MovieType, dar nu reușesc să-mi dau seama exact care ar putea fi problema.
Editare: o eroare pe care o primesc în try catch:
TypeError: movies.map is not a function
Am movies.map în componenta Container, care preia filmele de la Hero, care le ia din App:
const Container = ({movies}: MovieProps) => {
return (
<div className="container">
{movies.map((movie) =>(
<MovieItem movie={movie} key={movie.title}/>
))}
</div>
);
};
Nu știu de ce movies.map nu este o funcție dacă movies este practic un array.
Răspuns #1
Trebuie să adaugi „await fetchMovies” în loc de doar „fetchMovies”, dar pentru că nu poți face useEffect asincron, încearcă ceva de genul acesta...
useEffect(() =>{
async function foo(){
await fetchMovies();
}
foo();
}, []);
Sper că funcționează!
Răspunsul #2
Problema este că componenta Container încearcă să itereze peste movies înainte ca fetchMovies să fi terminat de obținut datele. Practic, încerci să iterezi peste un array gol. Pentru a evidenția acest lucru și în scopuri de depanare viitoare, include un console.log(movies) în Container.
Pentru a remedia, includeți pur și simplu movies.length ca verificare înainte de a parcurge datele cu map:
const Container = ({movies}: MovieProps) => {
return (
<div className="container">
{movies.length && movies.map((movie) =>(
<MovieItem movie={movie} key={movie.title}/>
))}
</div>
);
};
