I'm building a movies app in React and I'm using TMDB's api for that. I'm completely new to functional components and have a few queries. First I fetch all the genres using an api, and then iterate the genres one by one and call another API for fetching 20 movies in that genre.
The final data should look like this:
[{
genre: 'action',
movies: [],
},
{
genre: 'adventure',
movies: [],
}]
So that I can iterate the above array of objects and display the genre and its corresponding movies.
Right now, I'm stuck with the below code.
const [movieData, setMovieData] = useState([]);
const fetchGenres = async () => {
const url = `https://api.themoviedb.org/3/genre/movie/list?api_key=xxx&language=en-US`;
try {
const res = await fetch(url);
const data = await res.json();
setMovieData(data.genres);
} catch (err) {
console.error(err);
}
}
Now, coming to the queries,
Solutions are much appreciated!
To my mind it's better to keep your data separately. I mean array of genres and array of movies. So you will have:
const [genres, setGenres] = useState([]);
const [movies, setMovies] = useState([]);
then you make your async call to fetch genres and set it to state:
const fetchGenres = async () => {
const url = `https://baseurl/3/genre/movie/list?api_key=token&language=en-US`;
try {
const res = await fetch(url);
const data = await res.json();
setGenres(data.genres);
} catch (err) {
console.error(err);
}
};
React.useEffect(()=>{
fetchGenres();
},[]);
to find out that the genres were set you can create an effect, that will update each time when genres change:
async function fetchMovies() {
let result = [];
for (const genre of genres) {
const url = `https://baseurl/3/discover/movie?api_key=token&with_genres=${genre.id}`;
const res = await fetch(url);
const { results } = await res.json();
result = [...result, ...results];
}
setMovies(result);
}
React.useEffect(() => {
fetchMovies();
}, [genres]);
and finally we can use React.useMemo to calculate the result array we need according to genres and movies, it will be recalculated each time when one of the inner params change:
const resultArray = React.useMemo(() => {
return genres.map(genre => ({
genre,
movies: movies.filter((movie) => movie.genre_ids.includes(genre.id))
}));
}, [genres, movies])
I believe you will get an array like this
[{
genre: 'action',
movies: [],
},
{
genre: 'adventure',
movies: [],
}]