Cum să implementați derularea infinită și paginarea cu Next.js și TanStack Query

Majoritatea aplicațiilor pe care le veți dezvolta vor gestiona datele; pe măsură ce programele continuă să se extindă, poate exista o cantitate din ce în ce mai mare. Atunci când aplicațiile nu reușesc să gestioneze cantități mari de date în mod eficient, acestea funcționează slab.

Paginarea și derularea infinită sunt două tehnici populare pe care le puteți utiliza pentru a optimiza performanța aplicației. Ele vă pot ajuta să gestionați redarea datelor mai eficient și să îmbunătățiți experiența generală a utilizatorului.

Paginare și derulare infinită folosind TanStack Query

Interogare TanStack— o adaptare a React Query — este o bibliotecă robustă de gestionare a stării pentru aplicațiile JavaScript. Oferă o soluție eficientă pentru gestionarea stării aplicației, printre alte funcționalități, inclusiv sarcini legate de date, cum ar fi stocarea în cache.

Paginarea implică împărțirea unui set mare de date în pagini mai mici, permițând utilizatorilor să navigheze prin conținut în bucăți gestionabile folosind butoanele de navigare. În schimb, defilarea infinită oferă o experiență de navigare mai dinamică. Pe măsură ce utilizatorul derulează, datele noi se încarcă și se afișează automat, eliminând nevoia de navigare explicită.

Paginarea și derularea infinită au scopul de a gestiona și prezenta eficient cantități mari de date. Alegerea dintre cele două depinde de cerințele de date ale aplicației.

Puteți găsi codul acestui proiect în aceasta GitHub repertoriu.

Configurarea unui proiect Next.js

Pentru a începe, creați un proiect Next.js. Instalați cea mai recentă versiune a Next.js 13 care utilizează directorul App.

 npx create-next-app@latest next-project --app 

Apoi, instalați pachetul TanStack în proiectul dvs. folosind npm, managerul de pachete Node.

 npm i @tanstack/react-query 

Integrați TanStack Query în aplicația Next.js

Pentru a integra TanStack Query în proiectul dvs. Next.js, trebuie să creați și să inițializați o nouă instanță a TanStack Query în rădăcina aplicației – fișierul layout.js. Pentru a face acest lucru, importați QueryClient și QueryClientProvider din TanStack Query. Apoi, împachetați recuzita pentru copii cu QueryClientProvider, după cum urmează:

 "use client"
import React from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};

export default function RootLayout({ children }) {
  const queryClient = new QueryClient();

  return (
    <html lang="en">
      <body>
        <QueryClientProvider client={queryClient}>
          {children}
        </QueryClientProvider>
      </body>
    </html>
  );
}

export { metadata };

Această configurare asigură că TanStack Query are acces complet la starea aplicației.

  Cum să activezi chatul live 👋 pe site-ul tău?

Cârligul useQuery simplifică preluarea și gestionarea datelor. Prin furnizarea de parametri de paginare, cum ar fi numerele de pagină, puteți prelua cu ușurință anumite subseturi de date.

În plus, cârligul oferă diverse opțiuni și configurații pentru a vă personaliza funcționalitatea de preluare a datelor, inclusiv setarea opțiunilor de cache, precum și gestionarea eficientă a stărilor de încărcare. Cu aceste funcții, puteți crea fără efort o experiență de paginare perfectă.

Acum, pentru a implementa paginarea în aplicația Next.js, creați un fișier Pagination/page.js în directorul src/app. În interiorul acestui fișier, efectuați următoarele importuri:

 "use client"
import React, { useState } from 'react';
import { useQuery} from '@tanstack/react-query';
import './page.styles.css';

Apoi, definiți o componentă funcțională React. În cadrul acestei componente, trebuie să definiți o funcție care va prelua date de la un API extern. În acest caz, utilizați API-ul JSONPlaceholder pentru a prelua un set de postări.

 export default function Pagination() {
  const [page, setPage] = useState(1);

  const fetchPosts = async () => {
    try {
      const response = await fetch(`https://jsonplaceholder.typicode.com/posts?
                                  _page=${page}&_limit=10`);

      if (!response.ok) {
        throw new Error('Failed to fetch posts');
      }

      const data = await response.json();
      return data;
    } catch (error) {
      console.error(error);
      throw error;
    }
  };

  
}

Acum, definiți cârligul useQuery și specificați următorii parametri ca obiecte:

   const { isLoading, isError, error, data } = useQuery({
    keepPreviousData: true,
    queryKey: ['posts', page],
    queryFn: fetchPosts,
  });

Valoarea keepPreviousData este adevărată, ceea ce asigură că, în timp ce preia date noi, aplicația păstrează datele anterioare. Parametrul queryKey este o matrice care conține cheia pentru interogare, în acest caz, punctul final și pagina curentă pentru care doriți să obțineți date. În cele din urmă, parametrul queryFn, fetchPosts, declanșează apelul de funcție pentru a prelua date.

După cum am menționat mai devreme, cârligul oferă mai multe stări pe care le puteți despacheta, similar cu modul în care ați desstructura matrice și obiecte și le-ați utiliza pentru a îmbunătăți experiența utilizatorului (afișând interfețe de utilizare adecvate) în timpul procesului de preluare a datelor. Aceste stări includ isLoading, isError și multe altele.

  Cele mai bune 12 portofele Polkadot pentru gestionarea fără întreruperi a jetoanelor DOT

Pentru a face acest lucru, includeți următorul cod pentru a reda diferite ecrane de mesaje pe baza stării curente a procesului în curs:

   if (isLoading) {
    return (<h2>Loading...</h2>);
  }

  if (isError) {
    return (<h2 className="error-message">{error.message}</h2>);
  }

În cele din urmă, includeți codul pentru elementele JSX care se vor reda pe pagina browserului. Acest cod servește și alte două funcții:

  • Odată ce aplicația preia postările din API, acestea vor fi stocate în variabila de date furnizată de hook-ul useQuery. Această variabilă ajută la gestionarea stării aplicației. Puteți apoi să mapați lista de postări stocate în această variabilă și să le redați în browser.
  • Pentru a adăuga două butoane de navigare, Anterior și Următorul, pentru a permite utilizatorilor să interogheze și să afișeze date paginate suplimentare în consecință.
   return (
    <div>
      <h2 className="header">Next.js Pagination</h2>
      {data && (
        <div className="card">
          <ul className="post-list">
            {data.map((post) => (
                <li key={post.id} className="post-item">{post.title}</li>
            ))}
          </ul>
        </div>
      )}
      <div className="btn-container">
        <button
          onClick={() => setPage(prevState => Math.max(prevState - 1, 0))}
          disabled={page === 1}
          className="prev-button"
        >Prev Page</button>

        <button
          onClick={() => setPage(prevState => prevState + 1)}
          className="next-button"
        >Next Page</button>
      </div>
    </div>
  );

În cele din urmă, porniți serverul de dezvoltare.

 npm run dev 

Apoi, accesați http://localhost:3000/Pagination într-un browser.

Deoarece ați inclus folderul Pagination în directorul aplicației, Next.js îl tratează ca pe o rută, permițându-vă să accesați pagina la adresa URL respectivă.

Derularea infinită oferă o experiență de navigare perfectă. Un bun exemplu este YouTube, care preia automat videoclipuri noi și le afișează pe măsură ce derulați în jos.

Cârligul useInfiniteQuery vă permite să implementați derularea infinită prin preluarea datelor de la un server în pagini și preluarea și redarea automată a paginii următoare de date pe măsură ce utilizatorul derulează în jos.

Pentru a implementa derularea infinită, adăugați un fișier InfiniteScroll/page.js în directorul src/app. Apoi, efectuați următoarele importuri:

 "use client"
import React, { useRef, useEffect, useState } from 'react';
import { useInfiniteQuery } from '@tanstack/react-query';
import './page.styles.css';

Apoi, creați o componentă funcțională React. În interiorul acestei componente, similar implementării de paginare, creați o funcție care va prelua datele postărilor.

 export default function InfiniteScroll() {
  const listRef = useRef(null);
  const [isLoadingMore, setIsLoadingMore] = useState(false);

  const fetchPosts = async ({ pageParam = 1 }) => {
    try {
      const response = await fetch(`https://jsonplaceholder.typicode.com/posts?
                                  _page=${pageParam}&_limit=5`);

      if (!response.ok) {
        throw new Error('Failed to fetch posts');
      }

      const data = await response.json();
      await new Promise((resolve) => setTimeout(resolve, 2000));
      return data;
    } catch (error) {
      console.error(error);
      throw error;
    }
  };

  
}

Spre deosebire de implementarea de paginare, acest cod introduce o întârziere de două secunde la preluarea datelor pentru a permite unui utilizator să exploreze datele curente în timp ce derulează pentru a declanșa o recăpătare a unui nou set de date.

  Cum să trimiteți un fax gratuit de pe computer

Acum, definiți cârligul useInfiniteQuery. Când componenta se montează inițial, cârligul va prelua prima pagină de date de pe server. Pe măsură ce utilizatorul derulează în jos, cârligul va prelua automat următoarea pagină de date și o va reda în componentă.

   const { data, fetchNextPage, hasNextPage, isFetching } = useInfiniteQuery({
    queryKey: ['posts'],
    queryFn: fetchPosts,
    getNextPageParam: (lastPage, allPages) => {
      if (lastPage.length < 5) {
        return undefined;
      }
      return allPages.length + 1;
    },
  });

  const posts = data ? data.pages.flatMap((page) => page) : [];

Variabila posts combină toate postările din diferite pagini într-o singură matrice, rezultând o versiune aplatizată a variabilei de date. Acest lucru vă permite să mapați cu ușurință și să randați postările individuale.

Pentru a urmări derulările utilizatorilor și a încărca mai multe date atunci când utilizatorul se află aproape de partea de jos a listei, puteți defini o funcție care utilizează API-ul Intersection Observer pentru a detecta când elementele se intersectează cu fereastra.

   const handleIntersection = (entries) => {
    if (entries[0].isIntersecting && hasNextPage && !isFetching && !isLoadingMore) {
      setIsLoadingMore(true);
      fetchNextPage();
    }
  };

  useEffect(() => {
    const observer = new IntersectionObserver(handleIntersection, { threshold: 0.1 });

    if (listRef.current) {
      observer.observe(listRef.current);
    }

    return () => {
      if (listRef.current) {
        observer.unobserve(listRef.current);
      }
    };
  }, [listRef, handleIntersection]);

  useEffect(() => {
    if (!isFetching) {
      setIsLoadingMore(false);
    }
  }, [isFetching]);

În cele din urmă, includeți elementele JSX pentru postările care se redau în browser.

   return (
    <div>
      <h2 className="header">Infinite Scroll</h2>
      <ul ref={listRef} className="post-list">
        {posts.map((post) => (
          <li key={post.id} className="post-item">
            {post.title}
          </li>
        ))}
      </ul>
      <div className="loading-indicator">
        {isFetching ? 'Fetching...' : isLoadingMore ? 'Loading more...' : null}
      </div>
    </div>
  );

După ce ați făcut toate modificările, vizitați http://localhost:3000/InfiniteScroll pentru a le vedea în acțiune.

Interogare TanStack: Mai mult decât preluarea datelor

Paginarea și derularea infinită sunt exemple bune care evidențiază capabilitățile TanStack Query. Mai simplu spus, este o bibliotecă completă de gestionare a datelor.

Cu setul său extins de funcții, puteți eficientiza procesele de gestionare a datelor din aplicația dvs., inclusiv gestionarea eficientă a stării. Pe lângă alte sarcini legate de date, puteți îmbunătăți performanța generală a aplicațiilor dvs. web, precum și experiența utilizatorului.