No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Infinite Scrolling: limitando la carga de datos

12/20
Recursos

Aportes 15

Preguntas 1

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Para implementar el infine scrolling en todas las secciones, lo que hice fue lo siguiente:

  1. Crear (en main.js) una funci贸n llamada getPaginatedMovies que reciba todos los posibles par谩metros y realice la l贸gica de chequear los condicionales y hacer el llamado a la API de la siguiente p谩gina de resultados:
async function getPaginatedMovies(
    endPoint, 
    {
        categoryId, 
        query
    } = {},
    ) {
    const { 
        scrollTop, 
        scrollHeight, 
        clientHeight 
    } = document.documentElement;

    const scrollAtBottom = (scrollTop + clientHeight) >= (scrollHeight - 15);
    const pageIsNotMax = page < maxPage;

    if (scrollAtBottom && pageIsNotMax) {
        page++;

        const { data } = await api(endPoint, {
            params: {
                page,
                with_genres: categoryId,
                query,
            },
        });
        const movies = data.results;

        printMoviePosters(movies, genericSection, true);
    } 
}
  1. (en main.js) Cre茅 una funci贸n espec铆fica de paginaci贸n para cada secci贸n, en las que que llamaba a la funci贸n global de paginaci贸n, y si era necesario volv铆a a sacar la info del hash para pasarla por par谩metro:
function getPaginatedTrendingMovies() {
    getPaginatedMovies('/trending/movie/day');
}

function getPaginatedMoviesByCategory() {
    const [_, categoryData] = location.hash.split('=');
    const [categoryId] = categoryData.split('-');
    getPaginatedMovies('/discover/movie', {categoryId});
}

function getPaginatedMoviesBySearch() {
    const [_, undecodedQuery] = location.hash.split('=');
    const query = decodeURI(undecodedQuery);
    getPaginatedMovies('/search/movie', {undefined, query});
}
  1. (en navigation.js) La funci贸n de cada p谩gina asigna ahora a infiniteScroll su funci贸n propia de paginaci贸n:
function searchPage () {
   // funci贸n recortada
    infiniteScroll = getPaginatedMoviesBySearch;
}

function categoriesPage () {
   // funci贸n recortada
    infiniteScroll = getPaginatedMoviesByCategory;
}

function trendsPage () {
   // funci贸n recortada
    infiniteScroll = getPaginatedTrendingMovies;
}
  1. Luego me d铆 cuenta que si navegaba entre diferentes secciones, al compartir funci贸n page manten铆a acumulado el 煤ltimo n煤mero en el que quedaba, por lo que si llegaba a la p谩gina 4 en trendings, al cargar una categor铆a y scrollear, no me cargaba la p谩gina 2 sino la 5, y as铆 sucesivamente.
    Por lo tanto, (en navigation.js) reasign茅 a 1 la varible page antes de asignarle la funci贸n a infiniteScroll:
    page = 1;
    infiniteScroll = getPaginatedTrendingMovies;

De esta forma logr茅 que las 3 secciones tengan infinite scrolling, intentando mantenerme DRY

*Cualquier error o correci贸n, siempre s煤per bienvenido!

Yo resolv铆 el problema obteniendo el id desde el hash

location.hash.split('=')[1].split('-')[0]

cree una funcion paga searMovies y una funcion para moviesByCategory y desde ahi antes de hacer la peticion tome del hash el id que necesite,

const [_, urlId, urlName] = location.hash.split("=");
async function getPageCategoryMovies() {
    const {scrollTop, clientHeight, scrollHeight} = document.documentElement;

    const scrollIsButton = (scrollTop + clientHeight) >= (scrollHeight - 25);

    const [_, urlId, urlName] = location.hash.split("=");
    const limitMaxPage = page < limitPage;

    if (scrollIsButton && limitMaxPage) {
        page++;
        const { data } = await api('discover/movie', {
            params : {
                with_genres : urlId,
                page,
            },
        });
    
        const movies = data.results;
    
        loadImage(genericSection, movies, {lazy: true, clear: false,});
    }

}

y lo mismo para search

En mi caso hice una funci贸n 煤nica para manejar todos los botones de carga infinita, de search, de categories y de trending.

/**
 * Maneja toda la l贸gica de los botones de carga.
 * 
 * @param {string} url La url del endpoint.
 * @param {string} currentPage La p谩gina actual que se recibe de la respuesta del endpoint.
 * @param {string} totalPages La cantidad total de p谩ginas que se recibe del endpoint.
 * @param {string} container El contenedor principal o el section que est谩 visible.
 * @param {object} extraParams Par谩metros extra para mandar a la consulta.
 */
function loadMoreMoviesBtnHandler( url, currentPage, totalPages, container, extraParams ) {
    
    // Revisa si hay paginas para cargar.
    if (currentPage < totalPages) {

        // Crea el boton de carga y lo inserta unicamente en la seccion actual.
        const loadMoreBtn = document.createElement('button');

        loadMoreBtn.classList.add('loadMore');
        loadMoreBtn.innerText = 'Load More';
        loadMoreBtn.setAttribute('data-page', currentPage);

        // Agrega un observador al boton para disparar un evento de clic cuando sea visible.
        loadMoreMoviesObserver.observe(loadMoreBtn);

        container.appendChild(loadMoreBtn);

        // Agrega un event listener al boton.
        loadMoreBtn.addEventListener('click', async () => {
            let newCurrentPage = parseInt(loadMoreBtn.getAttribute('data-page')) + 1;

            const {data} = await api(url, {
                params: {
                    page: newCurrentPage,
                    ...extraParams
                }}
            );

            createMoviesMarkup(data.results, container, false);

            let lastNode = container.querySelector('.movie-container:last-child');
            lastNode.parentNode.insertBefore(loadMoreBtn, lastNode.nextSibling);
            loadMoreBtn.setAttribute('data-page', newCurrentPage);
        })
    }
    else {
        let loadMore = container.querySelectorAll('.loadMore');

        if ( loadMore.length ) {
            loadMore[0].remove();
        }
    }
}

Tambi茅n cre茅 un Observer en vez de un eventListener de scroll (me pareci贸 mas eficiente)

let loadMoreMoviesObserver = new IntersectionObserver((loadMoreObjetcs) => {
    loadMoreObjetcs.forEach(loadMoreButton => {
        
        if (loadMoreButton.isIntersecting) {
            loadMoreButton.target.click();
        }
    })
})

Y para llamar al handler lo hice as铆:

// Trending movies.
async function getTrendingMovies() {
    const endPoint = '/trending/movie/day';
    const {data} = await api(endPoint);

    const movies = data.results;

    createMoviesMarkup(movies, genericSection);
    loadMoreMoviesBtnHandler(endPoint, data.page, data.total_pages, genericSection);
}

// Search
async function getMoviesBySearch(query) {
    const endPoint = '/search/movie';
    const {data} = await api(endPoint, {
        params: {
            query,
        }
    });

    const movies = data.results;

    createMoviesMarkup(movies, genericSection);
    loadMoreMoviesBtnHandler(endPoint, data.page, data.total_pages, genericSection, {query});
}

// Categories
async function getMoviesByCategory(id) {
    const endPoint = '/discover/movie';
    const {data} = await api(endPoint, {
        params: {
            with_genres: id,
        }
    });

    const movies = data.results;

    createMoviesMarkup(movies, genericSection);
    loadMoreMoviesBtnHandler(endPoint, data.page, data.total_pages, genericSection, {with_genres: id});
}

Cuando intent茅 implementar el infinite scrolling por mi cuenta (de una forma distinta a la del Profesor Juan), tambi茅n pens茅 que una buena forma de aplicarlo para todas las dem谩s secciones ser铆a mediante clousures para que as铆 individualmente cada secci贸n 鈥渞ecuerde鈥 o 鈥済uarde鈥 la p谩gina actual en la que se encuentra . Sin embargo鈥 Al final ni siquiera me molest茅 en intentarlo debido a que en realidad (a pesar de que las conozco) no s茅 c贸mo crear ni usar las clousures, je je je 馃槄.

Por lo tanto al final termin茅 implementando todo de forma la cual dejar茅 por aqu铆~ Probablemente no sea la forma m谩s bonita ni 贸ptima, pero al menos funciona, je je 馃憠馃憟.

En mi soluci贸n, modifiqu茅 las funciones getTrendingMovies, getMoviesBySearch y getMoviesByCategory para que recibieran un par谩metro extra: el n煤mero de la p谩gina. De esta forma, cada vez que se llegue al final del scroll, simplemente se vuelve a llamar a las mismas funciones pero pas谩ndoles la p谩gina que se supone deben cargar.

// Get Trending Movies.
async function getTrendingMovies(page = 1) {
	try {
		thereAreSomeRequestsInProcess = true;
		const isTheFirstLoad = (page === 1);
		
		if (isTheFirstLoad) {
			genericSection.innerHTML = "";
			showMoviesLoadingScreen(genericSection);
			
			const { data } = await api(`trending/movie/day?page=${page}`);
			const movies = data.results;
			currentLimitPagination = data.total_pages;
			createMovies(movies, genericSection, isTheFirstLoad);

			console.group("Respuestas del Servidor (GET Trending Movies)");
				console.log(data);
			console.groupEnd();
		} else {
			if (page <= currentLimitPagination) {
				showInfiniteScrollingMoviesLoadingScreen(genericSection);
				
				currentPagination = page;
				const { data } = await api(`trending/movie/day?page=${page}`);
				const movies = data.results;
				currentLimitPagination = data.total_pages;
				createMovies(movies, genericSection, isTheFirstLoad);
				if (page === currentLimitPagination) showInfiniteScrollingEndMessage(genericSection);
				
				console.group("Respuestas del Servidor (GET Trending Movies by Scrolling)");
					console.log(data);
				console.groupEnd();
			}
		}
		
		thereAreSomeRequestsInProcess = false;
		
	} catch (error) {
		console.group("%cError (GET Trending Movies)", consoleErrorMessageStyle);
			console.error(error);
		console.groupEnd();
		alert("Ocurri贸 un Error en el GET de las Pel铆culas en Tendencia.");
	}
}


驴Y qui茅n se encarga de pasar el n煤mero de la p谩gina a cargar? Una funci贸n ubicada en el navigation.js donde tambi茅n est谩n las variables goblales que indican la p谩gina actual de la secci贸n y el l铆mite m谩ximo de la misma.

// Infinite Scrolling

let currentPagination = 1; // P谩gina Actual de la Secci贸n
let currentLimitPagination = null; // L铆mite de la Paginaci贸n Actual
let thereAreSomeRequestsInProcess = false;

document.addEventListener("scroll", loadMoreMoviesByInfiniteScrolling);
function loadMoreMoviesByInfiniteScrolling() {
	const {scrollTop, scrollHeight, clientHeight} = document.documentElement;
	const endOfScrollReached = (scrollTop+clientHeight) >= (scrollHeight-100);
	if (endOfScrollReached && !thereAreSomeRequestsInProcess)  {
		thereAreSomeRequestsInProcess = true;
		
		if (location.hash === "#trends") {
			console.log(`Se lleg贸 al final del scroll de la p谩gina ${currentPagination} en las tendencias.`);
			getTrendingMovies(currentPagination+1);
		}
		
		if (location.hash.startsWith("#search=")) {
			console.log(`Se lleg贸 al final del scroll de la p谩gina ${currentPagination} en la b煤squeda.`);
			const searchedTerm = location.hash.split("=")[1].trim();		
			getMoviesBySearch(searchedTerm, currentPagination+1);
		}
		
		if (location.hash.startsWith("#category=")) {
			console.log(`Se lleg贸 al final del scroll de la p谩gina ${currentPagination} en la categor铆a.`);
			const categoryId = location.hash.split("=")[1].split("-")[0];
			getMoviesByCategory(categoryId, currentPagination+1);
		}
	}
}

Yo implemente la solucion de obtener los parametros, ya sea el ID o el query, a traves de location.hash. Exactamente como lo hicimos en navigation.js.

No se si sea lo mas optimo pero funciona.

yo resolvi el problema asi:

infiniteScroll = () => {
    getPaginatedMoviesBySearch(realQuery)}```

A mi parecer es menos complicado de lo que parece, ya que, al cargar la 1ra pagina de nuestra seccion (seach o category) con location.hash podemos tomar ese id o ese query para hacer la solucitud de la 2da pagina y de las sucesivas. Espero haber sido claro y que pueda servirle a alguien!!

En mi solucion me sali de la tangente sin querer al elegir como primer funcion para implementar el infinite scrolling aquella que maneja las peliculas recomendadas dentro de la seccion movieDetail y me encontre con una serie de complicaciones a resolver sobre la marcha:
-La primera fue el hecho de que esta llamada a la API no debe utilizar la variable infiniteScrolling que definimos para los demas eventos de scroll debido a que trabaja con el scroll vertical de un contenedor y no con el scroll de la seccion visible en la que nos encontramos.
-La segunda fue que comprendi que en la clase previa nunca establecimos un reset en la variable 鈥減age鈥, por lo cual cada vez que la reutilizabamos en un ciclo de uso cotidiano de un usuario (entrar a una seccion, scrollear, salir, entrar a otra seccion, scrollear, etc) no arrancabamos desde la primer pagina disponible de la API, por lo que tuve que buscar el punto justo donde insertarle un reset sin que ello produzca problemas en el infinite scroll en si.
-Y por ultimo me parecia muy poco comodo el hecho de tener que arrastrar el scroll del contenedor 鈥渕anualmente鈥 para cargar mas peliculas debido a que eso provocaba muchas veces que la funcion se ejecutara varias veces consecutivas sin darme posibilidad de corregir la posicion del scroll y de esa forma evitar las multiples (si bien esto es algo a corregir en futuros updates), por lo cual termine implementado otro eventListener que se encargar de proveernos el scroll vertical con la rueda del mouse, tal cual lo hacemos en otras secciones.
A continuacion les dejo como quedaria el codigo:

Asi queda la navigation de la seccion movieDetails

function movieDetailsPage () {
    console.log("Movie!!")
    headerSection.classList.add('header-container--long');
    //headerSection.style.background = '';
    arrowBtn.classList.remove('inactive');
    arrowBtn.classList.add('header-arrow--white');
    headerTitle.classList.add('inactive');
    headerCategoryTitle.classList.add('inactive');
    searchForm.classList.add('inactive');

    trendingPreviewSection.classList.add('inactive');
    categoriesPreviewSection.classList.add('inactive');
    genericSection.classList.add('inactive');
    movieDetailSection.classList.remove('inactive');

    const [_, movieId] = location.hash.split('=') // ["#movie", 'movieID']
    getMovieDetailById(movieId);
    getRelatedMoviedById(movieId);
    //Aqui insertamos el reset de la pagina en esta funcion y en cualquier otra que haga uso del infiniteScroll
    page = 1;
}

Los eventos a escuchar dentro del contenedor

relatedMoviesContainer.addEventListener('scroll', getPaginatedRelatedMoviesbyId)
relatedMoviesContainer.addEventListener('wheel', scrollHorizontalContainer)

La funcion en si de llamada a la API

async function getPaginatedRelatedMoviesbyId() {
    const [_, movieId] = location.hash.split('=')
    const { scrollLeft, scrollWidth, clientWidth } = relatedMoviesContainer;

    const scrollIsEnd = (scrollLeft + clientWidth) >= (scrollWidth - 10);
    if (scrollIsEnd) {
        page++;
        const { data } = await api(urlSimilarMovies(movieId), {
            params: {
                page,
            }
    });
        const similarMovies = data.results;
        if (similarMovies) {
        movieRender(similarMovies, relatedMoviesContainer, {lazyLoad: true, clean: false});
        }
    }
}

Y por ultimo la funcion de scrollVertical haciendo uso del mouse

function scrollHorizontalContainer (event) {
	// Se puede modificar la velocidad corrigiendo el decimal
	relatedMoviesContainer.scrollLeft += event.deltaY * 0.50;
}

**Disclaimer
Hice uso del endpoint similarMovies debido a que testee muchas peliculas que no sean del todo populares (o son antiguas, etc) y el endpoint de Recommendations normalmente se encuentra vacio y por lo tanto no util para el uso de nuestra app

Yo lo resolv铆 pero el c贸digo es un desastre 馃槀

function infiniteScroll() {
	const scrollCond =
		document.documentElement.scrollTop + document.documentElement.clientHeight >= document.documentElement.scrollHeight;
	if (scrollCond && location.hash.startsWith("#trends")) {
		getTrendingMovies({ pag: pag, clear: false });
		pag++;
	}

	if (scrollCond && location.hash.startsWith("#category=")) {
		const hashContent = location.hash;
		const idAndName = hashContent.slice(10);
		const idAndNameArray = idAndName.split("-");
		const clicked_id = idAndNameArray[0];
		const clicked_name = idAndNameArray[1].replace("%20", " ");

		getMoviesByCategory(clicked_id, clicked_name, pag, false);
		pag++;
	}

	if (scrollCond && location.hash.startsWith("#search=")) {
		const hashContent = location.hash;
		const [_, hashContentArray] = hashContent.split("=");
		const searchValue = hashContentArray.replaceAll("%20", " ");
		searchMovies(searchValue, { pag: pag, clear: false });
		pag++;
	}
}

Yo us茅 generators, me qued贸 as铆 (est谩 hecho r谩pido, todav铆a tengo que limpiar el c贸digo)

Navigation.js

function printMoviesByGenre() {
    genre.classList.add('active')
    const regex = /category=(\d+)-(.*)/
    const genreData = regex.exec(location.hash)
    const id = genreData[1]
    const name = genreData[2]

    container = moviesByGenre
    getMoviesByGenre({ id, name })
    const page = generator(1)

    document.onscroll = () =>
        getPaginatedMovies('discover/movie', { with_genres: id }, page)
}

Index.js

let maxPage
let container
let page = 1
function* generator(i) {
    while (true) {
        i++
        yield i
    }
}
//...
async function getPaginatedMovies(endpoint, params = {}, pageGenerator) {
    if (page > maxPage) return
    const { scrollTop, scrollHeight, clientHeight } = document.documentElement
    const scrollIsInBottom = scrollTop + clientHeight >= scrollHeight - 30

    if (scrollIsInBottom) {
        page = pageGenerator.next().value
        params.page = page
        const { data } = await api(endpoint, {
            params,
        })
        const movies = data.results
        createCards(movies, container, false)
    }
}

Este es mi aporte, lo realic茅 antes de ver la clase 11 pero lo del passive no lo sab铆a XD, as铆 que lo agregu茅 despu茅s. En esta implementaci贸n creo el escuchador de scroll y mando a llamar la funci贸n inifityScroll en la cual se detectar谩 en que vista se est谩 parado y si se lleg贸 al m谩ximo scroll posible seg煤n cada condicional.

/* PAGINATION */
let page = 1; //Para las listas de trending y popular
window.addEventListener("scroll", infinityScroll, {passive : false});
function infinityScroll(){
    //Se extrae el m谩ximo scroll seg煤nla vista actual
    const maxScroll = document.documentElement.scrollHeight - window.innerHeight;
    if( (maxScroll === window.scrollY) && (location.hash === "#more-trends")){
        //Se aumenta la p谩gina
        page++;
        //Se manda a llamar la funci贸n de consulta
        trendingMovieViewMore();
        
    }
    if( (maxScroll === window.scrollY) && (location.hash === "#more-popular")){
        //Se aumenta la p谩gina
        page++;
        //Se manda a llamar la funci贸n de consulta
        popularMovieViewMore();
    }
    if( (maxScroll === window.scrollY) && (location.hash.startsWith("#category"))){
        //Se obtiene el id y nombre de categor铆a del hash usando split
        let [vista, categoryIdName] = location.hash.split("=");
        const [categoryId, categoryName] = categoryIdName.split("_");
        //Se aumenta la p谩gina
        page++;
        //Se manda a llamar la funci贸n de consulta
        getMovieByCategory({name: categoryName, id:categoryId});
    }
    if( (maxScroll === window.scrollY) && (location.hash.startsWith("#search"))){
        //Se obtiene el nombre de b煤squeda en el hash usando split y join
        let [vista, searchName] = location.hash.split("=");
        let query = searchName.split("-");
        query = query.join(" ");
        //Se aumenta la p谩gina
        page++;
        //Se manda a llamar la funci贸n de consulta
        getMovieBySearch({query});
    }   
}

En las funciones de consulta como trendingviewmore() etc; cada una tiene el par谩metro de page dentro de la consulta de axios. Adicional se agregan las siguientes
l铆neas para limpiar el contenedor de los posters de pel铆culas cuando es primera vez que se entra a dicha vista.

if(page <= 1)
   cardsContainer.innerHTML = ""; 

En navigation.js cada funci贸n de cambio de vista reiniciar谩 la variable global 鈥減age鈥 igual谩ndola a 1, por ejemplo:

function trendingListPage(){
  
 //Se quitan las vistas que no se deben mostrar y se deja s贸lo la deseada
    category.classList.add("d-none");
    movieDetail.classList.add("d-none");
    movieDetail.classList.add("d-md-none");
    searching.classList.add("d-none");
    trending.classList.add("d-none");
    popular.classList.add("d-none");
    popularList.classList.add("d-none");
    searchBar.classList.add("d-none");
    trendingList.classList.remove("d-none");
    //Se reinicia la paginaci贸n
    page = 1;
    //Se manda a llamar las funciones generadoras de la informaci贸n  
    trendingMovieViewMore();   
    window.scrollTo(0, 0);
}

aunque ese reinicio se puede hacer dentro de la funci贸n navigator tambi茅n, ya que el objetivo es detectar un cambio de vista y reiniciar la paginaci贸n.

Como bonus cree un bot贸n para hacer scroll hacia el top de las vistas ya que es dificil scrollear tanto luego de cargar mucha informaci贸n y funciona con este c贸digo:

/* SCROLLTOP BUTTON */
const scrollTop = document.getElementById("scroll-button");
scrollTop.addEventListener("click", () =>{
    window.scrollTo(0, 0);
})

Mi soluci贸n para el Infinite Scrolling en p谩ginas/secciones que reciben par谩metros fue guardar estos valores en variables globales (como hicimos con maxPage) para luego poder acceder a ellos desde la funci贸n de Infinite Scrolling.

  1. Cre茅 dos nuevas variables globales.
  • endpointInfiniteScroll: para guardar el endpoint y no tener que crear una funci贸n por cada secci贸n
  • infiniteScrollParams: para guardar los par谩metros como la categor铆a, b煤squeda, etc.
// navigation.js
let page = 1;
let maxPage;
let infiniteScroll;
let endpointInfiniteScroll;
let infiniteScrollParams = {
  params: {
    page: 1,
  },
};
  1. Luego, desde la primera petici贸n en la funci贸n GET asign茅 el endpoint y los par谩metros a las variables globales ya inicializadas.
// main.js 
async function getMoviesByCategory(id) {
  endpointInfiniteScroll = "/discover/movie?with-genres=";
  infiniteScrollParams = {
    params: {
      with_genres: id,
    },
  }

  const { data } = await api(endpointInfiniteScroll , infiniteScrollParams);

  maxPage = data.total_pages;

  createMovies(data.results, genericListMoviesPreview);

}
  1. Despu茅s, en la funci贸n del Infinite Scrolling us茅 las variables globales para realizar la petici贸n seg煤n los par谩metros y endpoint que se usaron para el primer GET.
//main.js 
async function getInfiniteMoviesList() {
  const { scrollTop, scrollHeight, clientHeight } = document.documentElement;

  const scrollIsBottom = (scrollTop + clientHeight >= scrollHeight - 15);

  const pageIsNotMax = (page < maxPage);

  if (scrollIsBottom && pageIsNotMax) {

    page++;

    infiniteScrollParams.params.page = page;
    
    const { data } = await api(endpointInfiniteScroll, infiniteScrollParams);

    createMovies(data.results, genericListMoviesPreview, {
      cleanSection: false,
    });

  }
  1. En la funci贸n 鈥渘avigator鈥 para cada vez que cambiemos de secci贸n establec铆 un valor inicial por defecto para estas variables, as铆, en secciones que no se necesiten estos valores no causen errores o se vayan acumulando.
//navigation.js
function navigator() {

  if(infiniteScroll){
    window.removeEventListener('scroll', infiniteScroll, {passive: false});
    infiniteScroll = undefined;
    page = 1;
    maxPage = 0;
    endpointInfiniteScroll = undefined;
    infiniteScrollParams = {
      params: {
        page: 1,
      },
    };
  }

}
  1. Por 煤ltimo, en la p谩gina o secci贸n que queramos usar el Infinite Scrolling asignamos su funci贸n a la variable global de 鈥渋nfiniteScroll鈥.
//navigation.js

function categoriesPage() {
// funci贸n recortada
  infiniteScroll = getInfiniteMoviesList;
}

La soluci贸n es crear esas funciones reutiilizables para que pueda usarse con p谩giina 1 hasta la p谩gina n, tambi茅n desde una funci贸n promesa podemos retornar un valor espec铆fico y cuando la usemos podemos catcharla con .then y all铆 hacer lo que queramos

const getTrendingMovies = async (page = 1) => {
    const dataUtil = {};
    try {
        const { status, data } = await api.get(URL_TRENDING_RES('movie', 'day'), {
            params: { page },
        });
        ...
        dataUtil.total_pages = data.total_pages;
    } catch (error) {
        ...
    }
    return dataUtil;
};

Para catcharla

const trendsPage = () => {
    ...
    getTrendingMovies().then((data) => {
        if (data.total_pages === 1) removeInfiniteScroll();
    });
    // Scroll infinito
    infiniteScroll = () => {
        if (scrollIsOnThreshold()) {
            getTrendingMovies(page).then((data) => {
                if (page >= data.total_pages) removeInfiniteScroll();
            });
        }
    };
};

.
.
Mi propuesta, commit actual: Click aqu铆

Para no tener problemas con los par谩metros, lo que hice es que esas variables que recibe se hagan globales鈥or ejemplo en el caso de searchMovies:

De tal manera que as铆 se puede aplicar la l贸gica del scroll infinito al igual que en trendingMovies