Effektiv Datahantering i Applikationer
De flesta applikationer som utvecklas hanterar data, och mängden data tenderar att öka när applikationerna växer. Om applikationer inte hanterar stora datamängder effektivt, kan det leda till sämre prestanda.
Paginering och oändlig rullning är två vanliga metoder för att optimera applikationens prestanda. Dessa tekniker hjälper till att hantera datahantering på ett effektivare sätt och förbättrar den övergripande användarupplevelsen.
Paginering och Oändlig Rullning med TanStack Query
TanStack Query, en vidareutveckling av React Query, är ett tillförlitligt bibliotek för tillståndshantering i JavaScript-applikationer. Det erbjuder en kraftfull lösning för att hantera applikationsstatus, inklusive datahanteringsuppgifter som cachning.
Paginering innebär att en stor datamängd delas upp i mindre sidor, vilket gör att användarna kan navigera i innehållet genom att använda navigeringsknappar. Oändlig rullning ger däremot en mer dynamisk användarupplevelse. När användaren rullar, laddas och visas ny data automatiskt, vilket eliminerar behovet av manuell navigering.
Både paginering och oändlig rullning syftar till att effektivt hantera och presentera stora mängder data. Valet av metod beror på applikationens specifika datakrav.
Projektets källkod finns tillgänglig i detta GitHub-arkiv.
Konfigurera ett Next.js-projekt
För att komma igång, skapa ett nytt Next.js-projekt. Installera den senaste versionen av Next.js 13 som använder appkatalogen:
npx create-next-app@latest next-project --app
Installera sedan TanStack-paketet i projektet med npm:
npm i @tanstack/react-query
Integrera TanStack Query i Next.js-applikationen
För att integrera TanStack Query i ditt Next.js-projekt, skapa och initiera en ny instans av TanStack Query i applikationens rotfil, layout.js. Importera QueryClient
och QueryClientProvider
från TanStack Query. Omslut sedan children
-props med QueryClientProvider
, som visas nedan:
"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 };
Denna konfiguration säkerställer att TanStack Query har fullständig tillgång till applikationens tillstånd.
useQuery
-hooken förenklar datahämtning och hantering. Genom att ange pagineringsparametrar, som sidnummer, kan du enkelt hämta specifika delmängder av data.
Dessutom erbjuder hooken olika alternativ och inställningar för att anpassa din datahämtningsfunktionalitet, inklusive cachningsalternativ och hantering av laddningstillstånd. Med dessa funktioner kan du skapa en sömlös pagineringsupplevelse.
För att implementera paginering i din Next.js-app, skapa en Pagination/page.js
-fil i katalogen src/app
. I den här filen, lägg till följande importer:
"use client" import React, { useState } from 'react'; import { useQuery} from '@tanstack/react-query'; import './page.styles.css';
Definiera sedan en funktionell React-komponent. Inuti komponenten definiera en funktion som hämtar data från ett externt API. I det här fallet använd JSONPlaceholder API för att hämta en uppsättning inlägg:
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; } }; }
Definiera nu useQuery
-hooken och ange följande parametrar som ett objekt:
const { isLoading, isError, error, data } = useQuery({ keepPreviousData: true, queryKey: ['posts', page], queryFn: fetchPosts, });
keepPreviousData
är satt till true, vilket gör att appen behåller tidigare data under hämtningen av ny data. Parametern queryKey
är en array som innehåller nyckeln för frågan, i det här fallet slutpunkten och aktuell sida. Slutligen anropar parametern queryFn
funktionen fetchPosts
för att hämta data.
Som tidigare nämnt ger hooken flera tillstånd som du kan använda för att förbättra användarupplevelsen, till exempel isLoading
, isError
, etc.
Inkludera följande kod för att visa olika meddelanden beroende på den aktuella dataladdningsprocessen:
if (isLoading) { return (<h2>Loading...</h2>); } if (isError) { return (<h2 className="error-message">{error.message}</h2>); }
Slutligen, lägg till koden för JSX-elementen som ska visas på webbsidan. Koden innehåller även två andra funktioner:
- När appen hämtar inläggen från API:et lagras de i variabeln data som tillhandahålls av
useQuery
-hooken. Du kan sedan iterera genom inläggen som lagras i den variabeln och visa dem i webbläsaren. - Lägga till navigeringsknappar (Föregående och Nästa) så att användarna kan visa fler sidnumrerade data.
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> );
Starta utvecklingsservern:
npm run dev
Gå sedan till http://localhost:3000/Pagination i webbläsaren.
Eftersom du har inkluderat pagineringsmappen i appkatalogen behandlar Next.js den som en rutt, vilket gör att du kan nå sidan på den adressen.
Oändlig rullning ger en sömlös användarupplevelse. Ett bra exempel är YouTube som laddar nya videor automatiskt medan du scrollar ned.
useInfiniteQuery
-hooken gör det möjligt att implementera oändlig rullning genom att hämta data från en server i sidor och automatiskt ladda nästa sida med data medan användaren scrollar nedåt.
För att implementera oändlig rullning, lägg till en InfiniteScroll/page.js
-fil i katalogen src/app
. Lägg sedan till följande importer:
"use client" import React, { useRef, useEffect, useState } from 'react'; import { useInfiniteQuery } from '@tanstack/react-query'; import './page.styles.css';
Skapa sedan en funktionell React-komponent. Inuti komponenten, liknande pagineringsimplementeringen, skapa en funktion som hämtar inläggsdata:
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; } }; }
Till skillnad från pagineringsimplementeringen, introducerar den här koden en två sekunders fördröjning vid hämtning av data, så att användaren kan utforska aktuell data medan de scrollar för att utlösa hämtning av ny data.
Definiera nu useInfiniteQuery
-hooken. När komponenten först monteras hämtar hooken den första sidan med data från servern. När användaren scrollar ned, hämtar hooken automatiskt nästa sida och renderar den i komponenten:
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) : [];
Variabeln posts
kombinerar alla inlägg från olika sidor till en enda array, vilket resulterar i en utplattad version av datavariabeln. Detta gör det enkelt att iterera och visa enskilda inlägg.
För att spåra användarrullning och ladda mer data när användaren är nära botten av listan, kan du definiera en funktion som använder Intersection Observer API för att upptäcka när element korsar visningsporten:
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]);
Slutligen, inkludera JSX-elementen för inläggen som ska visas i webbläsaren:
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> );
När du har gjort alla ändringar, besök http://localhost:3000/InfiniteScroll för att se dem i funktion.
TanStack Query: Mer än Bara Datahämtning
Paginering och oändlig rullning är bra exempel som visar kapaciteten hos TanStack Query. Det är kort sagt ett mångsidigt datahanteringsbibliotek.
Med dess omfattande uppsättning funktioner kan du effektivisera appens datahanteringsprocesser, inklusive effektiv hantering av tillstånd. Tillsammans med andra datarelaterade uppgifter kan du förbättra den övergripande prestandan och användarupplevelsen i dina webbapplikationer.