Skip to content

Commit

Permalink
Merge pull request #39 from simonc56/prefetch
Browse files Browse the repository at this point in the history
  • Loading branch information
simonc56 authored Nov 18, 2024
2 parents 39c529c + 41443af commit f0108e3
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 41 deletions.
10 changes: 10 additions & 0 deletions src/components/Homepage/Homepage.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { Button, Paper } from '@mantine/core';
import { useEffect } from 'react';
import { BsInstagram, BsTwitterX, BsYoutube } from 'react-icons/bs';
import { ImFacebook2 } from 'react-icons/im';
import { moviesApiSlice } from '../../features/moviesApiSlice';
import './Homepage.scss';
import LastReviews from './LastReviews/LastReviews';
import NewsFeed from './NewsFeed/NewsFeed';
import PosterCarousel from './PosterCarousel/PosterCarousel';

function Homepage() {
const prefetchMovies = moviesApiSlice.usePrefetch('getMoviesByFilter');
const prefetchMovieList = moviesApiSlice.usePrefetch('getMoviesByParams');

useEffect(() => {
prefetchMovies('nowplaying');
prefetchMovieList({ page: 1, sort_by: 'popularity.desc', with_genres: '' });
}, [prefetchMovies, prefetchMovieList]);

return (
<div className="homepage">
<div className="hero">
Expand Down
55 changes: 14 additions & 41 deletions src/components/MoviesPage/MoviesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { Badge, Button, Card, Image, Text } from '@mantine/core';
import { useEffect, useState } from 'react';
import { useState } from 'react';
import { Link } from 'react-router-dom';
import { MoviesFilter } from '../../@types/MovieState';
import MovieType from '../../@types/MovieType';
import { getMovieById } from '../../apiHandler/api';
import no_poster from '../../assets/no-poster.webp';
import { useGetMoviesByFilterQuery } from '../../features/moviesApiSlice';
import { useGetMoviesByFilterQuery, useGetMoviesDetailsQuery } from '../../features/moviesApiSlice';
import { useAppSelector } from '../../store/hooks';
import ButtonAddToPlaylist from '../ui/ButtonAddToPlaylist/ButtonAddToPlaylist';
import Loader from '../ui/Loader/Loader';
Expand All @@ -26,50 +24,25 @@ const truncateTextWithSlice = (text: string, maxLength: number) =>
function MoviesPage({ title, filter }: { title: string; filter: MoviesFilter }) {
const { data: movieList } = useGetMoviesByFilterQuery(filter);
const logged = useAppSelector((state) => state.settings.user.logged);
const [detailedMovies, setDetailedMovies] = useState<MovieType[]>([]);
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc');
const [loading, setLoading] = useState<boolean>(true);

useEffect(() => {
async function fetchDetails() {
if (!movieList || movieList.length === 0) {
return;
}
setLoading(true);
// impossible to use RTK Query here
const promisesList = movieList.map((movie) =>
getMovieById(movie.tmdb_id.toString())
.then((response) => ({ ...movie, ...response.data.data }))
.catch((error) => {
// eslint-disable-next-line no-console
console.error(`Error fetching details for movie ${movie.tmdb_id}:`, error);
})
);
try {
const results = await Promise.all(promisesList);
setDetailedMovies(results);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Error fetching movie details:', error);
} finally {
setLoading(false);
}
}
fetchDetails();
}, [movieList]);

const sortedMovieList = detailedMovies.slice().sort((a, b) => {
if (sortOrder === 'asc') {
return new Date(a.release_date).getTime() - new Date(b.release_date).getTime();
}
return new Date(b.release_date).getTime() - new Date(a.release_date).getTime();
const { data: detailedMovies, isLoading } = useGetMoviesDetailsQuery(movieList || [], {
skip: !movieList || movieList.length === 0,
});

const sortedMovieList = detailedMovies?.length
? detailedMovies.slice().sort((a, b) => {
if (sortOrder === 'asc') {
return new Date(a.release_date).getTime() - new Date(b.release_date).getTime();
}
return new Date(b.release_date).getTime() - new Date(a.release_date).getTime();
})
: [];

const toggleSortOrder = () => {
setSortOrder((prevSortOrder) => (prevSortOrder === 'asc' ? 'desc' : 'asc'));
};

return loading ? (
return isLoading ? (
<div className={classes.loaderContainer}>
<Loader />
</div>
Expand Down
19 changes: 19 additions & 0 deletions src/features/moviesApiSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ export const moviesApiSlice = apiSlice.enhanceEndpoints({ addTagTypes: ['MovieUs
query: (filter: MoviesFilter) => ({
url: `/movie/${filter}`,
}),
async onQueryStarted(_params, { dispatch, queryFulfilled }) {
// Prefetch all movies of the list
const { data: movies } = await queryFulfilled;
movies.forEach((movie: MovieType) => {
dispatch(moviesApiSlice.endpoints.getMovieById.initiate(movie.tmdb_id.toString()));
});
},
}),
getMoviesDetails: builder.query<MovieType[], MovieType[]>({
// Fetch all movies of the list
async queryFn(movieList: MovieType[], { dispatch }): Promise<{ data: MovieType[] }> {
const detailPromises = movieList.map((movie) =>
dispatch(moviesApiSlice.endpoints.getMovieById.initiate(movie.tmdb_id.toString()))
);
const results = await Promise.all(detailPromises);
const data = results.map((result) => result.data).filter((movie): movie is MovieType => !!movie);
return { data };
},
}),
getGenres: builder.query<Genre[], void>({
query: () => ({
Expand Down Expand Up @@ -195,6 +213,7 @@ export const {
useGetUserdataMovieByIdQuery,
useGetMoviesByParamsQuery,
useGetMoviesByFilterQuery,
useGetMoviesDetailsQuery,
useGetGenresQuery,
useSearchMoviesQuery,
usePostReviewMutation,
Expand Down

0 comments on commit f0108e3

Please sign in to comment.