Maison > interface Web > js tutoriel > Comment utiliser les requêtes Infinity (TanStack Query) pour effectuer un défilement infini

Comment utiliser les requêtes Infinity (TanStack Query) pour effectuer un défilement infini

Mary-Kate Olsen
Libérer: 2024-11-10 10:01:02
original
612 Les gens l'ont consulté

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
Copier après la connexion

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
Copier après la connexion

Dans le fichier App.tsx, vous verrez que votre code ressemble à ceci :

How to use Infinity Queries (TanStack Query) to do infinite scrolling

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
    }
})
Copier après la connexion

Explication de chaque paramètre :

  • queryFn : la fonction chargée de renvoyer les données de notre requête ; il reçoit la page courante en paramètre.
  • queryKey : sert d'identifiant pour votre requête, agissant également comme un tableau de dépendances. Chaque fois qu'une variable que vous y transmettez change, useInfiniteQuery la récupère automatiquement.
  • initialPageParam : la valeur initiale par défaut.
  • getNextPageParam : reçoit tout ce que renvoie votre fonction queryFn et doit renvoyer le numéro de page suivant à demander.

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
  }
} 
Copier après la connexion

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>
Copier après la connexion

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()
  }
}
Copier après la connexion

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>
  )
}
Copier après la connexion

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!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal