Voici votre message traduit en anglais :
Dans cet article, je vais vous apprendre à implémenter le défilement infini à l'aide de TanStack Query, en particulier avec Infinity Queries. Nous allons créer un flux photo avec Vite et mettre en place un défilement infini. Pour commencer, ouvrez votre terminal et exécutez la commande suivante pour cloner un projet avec des configurations de base :
git clone --branch start https://github.com/DAVI-REZENDE/photos-feed.git cd photos-feed npm i
Tout est prêt ! Maintenant, implémentons la fonctionnalité de défilement infini à l'aide de la bibliothèque TanStack Query. Installez-le avec la commande ci-dessous :
npm i @tanstack/react-query npm i axios
Dans le fichier App.tsx, vous verrez que votre code ressemble à ceci :
Tout d’abord, nous allons remplacer useEffect par useInfiniteQuery, le hook chargé de gérer nos requêtes infinies. Nous devons lui fournir deux propriétés : queryKey et queryFn, comme suit :
const { data, isLoading, fetchNextPage, isFetchingNextPage, isFetching, hasNextPage } = useInfiniteQuery({ queryFn: fetchPhotos, queryKey: ['photos'], initialPageParam: 1, getNextPageParam: (lastPage) => { return lastPage.nextPage } })
Nous devrons modifier la fonction fetchPhotos :
async function fetchPhotos({ pageParam }: { pageParam: number }) { const response = await api.get<ImageData[]>('/photos', { params: { page: pageParam, per_page: 5, } }) return { data: response.data, nextPage: pageParam + 1 } }
Le hook useInfiniteQuery renvoie les données en pages, donc notre rendu changera légèrement :
<main className="h-screen w-screen bg-zinc-950 flex flex-col gap-6 p-6 items-center text-white overflow-auto"> {isLoading ? 'Loading...' : ( <> {data?.pages.map((group, i) => ( <div className="flex flex-col gap-6" key={i}> {group.data.map(({ id, urls }) => ( <img className="aspect-square rounded-md h-[550px] object-cover" src={urls.regular} key={id} /> ))} </div> ))} <div> <button onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage} > {isFetchingNextPage ? 'Loading more...' : hasNextPage ? 'Load More' : 'Nothing more to load'} </button> </div> <div>{isFetching && !isFetchingNextPage ? 'Fetching...' : null}</div> </> )} </main>
Désormais, chaque fois que l'utilisateur atteint la fin du parchemin et clique sur le bouton « Charger plus », les données seront automatiquement ajoutées.
Pour récupérer la page suivante chaque fois que l'utilisateur atteint la fin du défilement sans avoir besoin de cliquer sur le bouton, ajoutez simplement la fonction suivante :
function handleScroll(event: UIEvent<HTMLElement>) { const { scrollTop, clientHeight, scrollHeight } = event.currentTarget if (scrollTop + clientHeight >= scrollHeight) { fetchNextPage() } }
Et ajoutez l'événement onScroll dans le div qui enveloppe votre liste, en appelant la fonction ici. Fait! Désormais, chaque fois que l'utilisateur fait défiler jusqu'à la fin, de nouvelles données seront automatiquement chargées.
Au final, votre code devrait ressembler à ceci :
import { useInfiniteQuery } from "@tanstack/react-query" import { UIEvent } from "react" import { api } from "./lib/api" type ImageData = { id: string, urls: { regular: string } } export function Home() { async function fetchPhotos({ pageParam }: { pageParam: number }) { const response = await api.get<ImageData[]>('/photos', { params: { page: pageParam, per_page: 5, } }) return { data: response.data, nextPage: pageParam + 1 } } const { data, isLoading, fetchNextPage, isFetchingNextPage, isFetching, hasNextPage } = useInfiniteQuery({ queryFn: fetchPhotos, queryKey: ['photos'], initialPageParam: 1, getNextPageParam: (lastPage) => { return lastPage.nextPage } }) function handleScroll(event: UIEvent<HTMLElement>) { const { scrollTop, clientHeight, scrollHeight } = event.currentTarget if (scrollTop + clientHeight >= scrollHeight) { fetchNextPage() } }; return ( <main className="h-screen w-screen bg-zinc-950 flex flex-col gap-6 p-6 items-center text-white overflow-auto" onScroll={handleScroll}> {isLoading ? 'Loading...' : ( <> {data?.pages.map((group, i) => ( <div className="flex flex-col gap-6" key={i}> {group.data.map(({ id, urls }) => ( <img className="aspect-square rounded-md h-[550px] object-cover" src={urls.regular} key={id} /> ))} </div> ))} <div> <button onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage} > {isFetchingNextPage ? 'Loading more...' : hasNextPage ? 'Load More' : 'Nothing more to load'} </button> </div> <div>{isFetching && !isFetchingNextPage ? 'Fetching...' : null}</div> </> )} </main> ) }
Merci !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!