Większość aplikacji, które stworzysz, będzie zarządzać danymi; w miarę zwiększania się skali programów może być ich coraz więcej. Jeśli aplikacje nie zarządzają skutecznie dużymi ilościami danych, działają słabo.
Paginacja i nieskończone przewijanie to dwie popularne techniki, których można użyć do optymalizacji wydajności aplikacji. Mogą pomóc w wydajniejszym renderowaniu danych i poprawić ogólne wrażenia użytkownika.
Spis treści:
Paginacja i nieskończone przewijanie za pomocą zapytania TanStack
Zapytanie TanStack—adaptacja React Query — to solidna biblioteka do zarządzania stanem dla aplikacji JavaScript. Oferuje wydajne rozwiązanie do zarządzania stanem aplikacji, a także innymi funkcjonalnościami, w tym zadaniami związanymi z danymi, takimi jak buforowanie.
Paginacja polega na podzieleniu dużego zbioru danych na mniejsze strony, umożliwiając użytkownikom nawigację po treści w łatwych do zarządzania fragmentach za pomocą przycisków nawigacyjnych. Natomiast nieskończone przewijanie zapewnia bardziej dynamiczne przeglądanie. Gdy użytkownik przewija, nowe dane ładują się i wyświetlają automatycznie, eliminując potrzebę jawnej nawigacji.
Paginacja i nieskończone przewijanie mają na celu efektywne zarządzanie i prezentację dużych ilości danych. Wybór pomiędzy nimi zależy od wymagań aplikacji dotyczących danych.
Kod tego projektu znajdziesz w this GitHub magazyn.
Konfigurowanie projektu Next.js
Aby rozpocząć, utwórz projekt Next.js. Zainstaluj najnowszą wersję Next.js 13, która korzysta z katalogu aplikacji.
npx create-next-app@latest next-project --app
Następnie zainstaluj pakiet TanStack w swoim projekcie za pomocą npm, menedżera pakietów Node.
npm i @tanstack/react-query
Zintegruj zapytanie TanStack z aplikacją Next.js
Aby zintegrować TanStack Query z projektem Next.js, musisz utworzyć i zainicjować nową instancję TanStack Query w katalogu głównym aplikacji – plik układ.js. Aby to zrobić, zaimportuj QueryClient i QueryClientProvider z TanStack Query. Następnie zawiń element dziecięcy za pomocą QueryClientProvider w następujący sposób:
"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 };
Ta konfiguracja zapewnia, że TanStack Query ma pełny dostęp do stanu aplikacji.
Hak useQuery usprawnia pobieranie danych i zarządzanie nimi. Podając parametry paginacji, takie jak numery stron, można łatwo pobrać określone podzbiory danych.
Dodatkowo hak zapewnia różne opcje i konfiguracje umożliwiające dostosowanie funkcjonalności pobierania danych, w tym ustawianie opcji pamięci podręcznej, a także efektywną obsługę stanów ładowania. Dzięki tym funkcjom możesz z łatwością stworzyć płynną paginację.
Teraz, aby zaimplementować paginację w aplikacji Next.js, utwórz plik Pagination/page.js w katalogu src/app. Wewnątrz tego pliku dokonaj następującego importu:
"use client"
import React, { useState } from 'react';
import { useQuery} from '@tanstack/react-query';
import './page.styles.css';
Następnie zdefiniuj komponent funkcjonalny React. Wewnątrz tego komponentu musisz zdefiniować funkcję, która będzie pobierać dane z zewnętrznego API. W takim wypadku skorzystaj z API zastępcze JSON aby pobrać zestaw postów.
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;
}
};
}
Teraz zdefiniuj hak useQuery i określ następujące parametry jako obiekty:
const { isLoading, isError, error, data } = useQuery({
keepPreviousData: true,
queryKey: ['posts', page],
queryFn: fetchPosts,
});
Wartość keepPreviousData ma wartość true, co gwarantuje, że podczas pobierania nowych danych aplikacja zachowa poprzednie dane. Parametr queryKey to tablica zawierająca klucz zapytania, w tym przypadku punkt końcowy i bieżącą stronę, dla której chcesz pobrać dane. Na koniec parametr queryFn fetchPosts wyzwala wywołanie funkcji w celu pobrania danych.
Jak wspomniano wcześniej, hak udostępnia kilka stanów, które można rozpakować, podobnie jak niszczy się tablice i obiekty i wykorzystuje je do poprawy komfortu użytkownika (renderowania odpowiednich interfejsów użytkownika) podczas procesu pobierania danych. Stany te obejmują isLoading, isError i inne.
Aby to zrobić, dołącz następujący kod, aby wyświetlić różne ekrany komunikatów w zależności od bieżącego stanu trwającego procesu:
if (isLoading) {
return (<h2>Loading...</h2>);
}if (isError) {
return (<h2 className="error-message">{error.message}</h2>);
}
Na koniec dołącz kod elementów JSX, które będą renderowane na stronie przeglądarki. Kod ten pełni także dwie inne funkcje:
- Gdy aplikacja pobierze posty z API, zostaną one zapisane w zmiennej danych dostarczonej przez hak useQuery. Ta zmienna pomaga zarządzać stanem aplikacji. Następnie możesz zmapować listę postów przechowywanych w tej zmiennej i wyrenderować je w przeglądarce.
- Aby dodać dwa przyciski nawigacyjne, Poprzedni i Następny, aby umożliwić użytkownikom wysyłanie zapytań i wyświetlanie dodatkowych danych podzielonych na strony.
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>
);
Na koniec uruchom serwer deweloperski.
npm run dev
Następnie przejdź do http://localhost:3000/Pagination w przeglądarce.
Ponieważ folder Pagination znalazł się w katalogu aplikacji, Next.js traktuje go jako trasę, umożliwiając dostęp do strony pod tym adresem URL.
Nieskończone przewijanie zapewnia płynne przeglądanie. Dobrym przykładem jest YouTube, który automatycznie pobiera nowe filmy i wyświetla je podczas przewijania w dół.
Hak useInfiniteQuery umożliwia zaimplementowanie nieskończonego przewijania poprzez pobieranie danych z serwera na stronach oraz automatyczne pobieranie i renderowanie następnej strony danych, gdy użytkownik przewija w dół.
Aby zaimplementować nieskończone przewijanie, dodaj plik InfiniteScroll/page.js w katalogu src/app. Następnie wykonaj następujący import:
"use client"
import React, { useRef, useEffect, useState } from 'react';
import { useInfiniteQuery } from '@tanstack/react-query';
import './page.styles.css';
Następnie utwórz komponent funkcjonalny React. Wewnątrz tego komponentu, podobnie jak w przypadku implementacji paginacji, utwórz funkcję, która będzie pobierać dane z postów.
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;
}
};
}
W przeciwieństwie do implementacji paginacji, ten kod wprowadza dwusekundowe opóźnienie podczas pobierania danych, aby umożliwić użytkownikowi eksplorację bieżących danych podczas przewijania i wyzwolenie ponownego pobrania nowego zestawu danych.
Teraz zdefiniuj hak useInfiniteQuery. Gdy komponent zostanie początkowo zamontowany, hak pobierze pierwszą stronę danych z serwera. Gdy użytkownik przewija w dół, hak automatycznie pobierze następną stronę danych i wyrenderuje ją w komponencie.
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) : [];
Zmienna posty łączy wszystkie posty z różnych stron w jedną tablicę, co daje spłaszczoną wersję zmiennej danych. Umożliwia to łatwe mapowanie i renderowanie poszczególnych postów.
Aby śledzić przewijanie użytkownika i ładować więcej danych, gdy użytkownik znajduje się blisko dołu listy, można zdefiniować funkcję wykorzystującą interfejs API Intersection Observer do wykrywania, kiedy elementy przecinają się z rzutnią.
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]);
Na koniec dołącz elementy JSX do postów renderowanych w przeglądarce.
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>
);
Po wprowadzeniu wszystkich zmian odwiedź http://localhost:3000/InfiniteScroll, aby zobaczyć je w akcji.
Zapytanie TanStack: więcej niż tylko pobieranie danych
Paginacja i nieskończone przewijanie to dobre przykłady podkreślające możliwości TanStack Query. Mówiąc najprościej, jest to wszechstronna biblioteka do zarządzania danymi.
Dzięki rozbudowanemu zestawowi funkcji możesz usprawnić procesy zarządzania danymi aplikacji, w tym wydajną obsługę stanu. Oprócz innych zadań związanych z danymi możesz poprawić ogólną wydajność aplikacji internetowych, a także komfort użytkowania.