So I have an app which uses Movies API. I make an API request, then I pass this data to an array using useState hook, basically my code looks like the following:
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>
);
}
So basically, when I run the app, I get an alert with an error. I've tried renaming the useState, so it differs from props in the <Hero> component, and then I could pass data to an array. But when I do it with [movies, setMovies] it doesn't work. So I guess the problem is somewhere in passing props or type MovieType, but I can't figure out what exactly could be the problem.
Edit: an error I get in try catch:
TypeError: movies.map is not a function
I have movies.map in Container component, which gets movies from the Hero, which gets it from the App:
const Container = ({movies}: MovieProps) => {
return (
<div className="container">
{movies.map((movie) =>(
<MovieItem movie={movie} key={movie.title}/>
))}
</div>
);
};
I don't know why movies.map is not a function if movies is basically an array.
CodePudding user response:
You have to add "await fetchMovies" instead of just "fetchMovies" but since you can't make useEffect async try something like this...
useEffect(() =>{
async function foo(){
await fetchMovies();
}
foo();
}, []);
Hopefully it works!
CodePudding user response:
The problem is that Container component attempting to iterate over movies before fetchMovies has finished getting the data. Essentially, you're trying to iterate over an empty array. To reveal this, and for future debugging purposes, include a console.log(movies) in Container.
To fix, simply include movies.length as a check before you map over the data:
const Container = ({movies}: MovieProps) => {
return (
<div className="container">
{movies.length && movies.map((movie) =>(
<MovieItem movie={movie} key={movie.title}/>
))}
</div>
);
};
