Обробка даних є ключовим аспектом багатьох програмних проєктів. Зі збільшенням обсягу даних, ефективне управління ними стає критично важливим для забезпечення високої продуктивності програм. Неефективна обробка великих масивів інформації може призвести до значного погіршення роботи застосунків.
Для оптимізації продуктивності та зручності користування, застосовуються такі методи, як пагінація та нескінченне прокручування. Ці підходи дозволяють ефективно працювати з великими обсягами даних, забезпечуючи при цьому плавну та приємну взаємодію з користувачем.
Пагінація та нескінченне прокручування з використанням TanStack Query
TanStack Query, адаптація React Query, є потужною бібліотекою для управління станом в JavaScript-програмах. Вона надає ефективні рішення для обробки стану, включаючи операції з даними, такі як кешування.
Пагінація передбачає поділ великих наборів даних на окремі сторінки, дозволяючи користувачам переміщатися між ними за допомогою кнопок навігації. Натомість, нескінченне прокручування створює динамічний досвід перегляду, де нові дані автоматично завантажуються при прокручуванні сторінки, усуваючи необхідність у явній навігації.
Обидва методи служать для ефективного управління та представлення великих обсягів даних. Вибір між пагінацією та нескінченним прокручуванням залежить від конкретних вимог вашого застосунку.
Приклад коду цього проєкту доступний на GitHub.
Налаштування проєкту Next.js
Для початку роботи створіть новий проєкт Next.js. Ми рекомендуємо використовувати останню версію Next.js 13, яка підтримує каталог App.
npx create-next-app@latest next-project --app
Потім встановіть пакет TanStack у ваш проєкт за допомогою npm:
npm i @tanstack/react-query
Інтеграція TanStack Query в застосунок Next.js
Для інтеграції TanStack Query у ваш проєкт Next.js, потрібно створити та ініціалізувати новий екземпляр TanStack Query у файлі layout.js, який є кореневим файлом програми. Імпортуйте QueryClient та QueryClientProvider з TanStack Query та оберніть дочірній пропс за допомогою QueryClientProvider:
"use client"
import React from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';const metadata = {
title: 'Створити Next App',
description: 'Згенеровано create next app',
};export default function RootLayout({ children }) {
const queryClient = new QueryClient();return (
<html lang="uk">
<body>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</body>
</html>
);
}export { metadata };
Це забезпечує повний доступ TanStack Query до стану програми.
Хук useQuery спрощує отримання та обробку даних. Використовуючи параметри пагінації, такі як номери сторінок, можна легко отримувати певні підмножини даних.
Крім того, хук надає різні налаштування для конфігурації функцій отримання даних, включаючи параметри кешування та обробку станів завантаження. Це дозволяє створювати безшовну реалізацію пагінації.
Для реалізації пагінації у вашому Next.js-застосунку, створіть файл Pagination/page.js у каталозі src/app. У цьому файлі необхідно виконати наступні імпорти:
"use client"
import React, { useState } from 'react';
import { useQuery} from '@tanstack/react-query';
import './page.styles.css';
Далі визначте функціональний React-компонент. Всередині цього компонента необхідно визначити функцію, яка отримуватиме дані із зовнішнього API. У цьому прикладі буде використано JSONPlaceholder API для отримання набору публікацій.
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('Не вдалося отримати публікації');
}const data = await response.json();
return data;
} catch (error) {
console.error(error);
throw error;
}
};
}
Тепер визначте хук useQuery та вкажіть наступні параметри у вигляді об’єктів:
const { isLoading, isError, error, data } = useQuery({
keepPreviousData: true,
queryKey: ['posts', page],
queryFn: fetchPosts,
});
keepPreviousData встановлено на true, що гарантує збереження попередніх даних під час отримання нових. queryKey — це масив, який містить ключ для запиту, у цьому випадку це кінцева точка та номер поточної сторінки. Параметр queryFn, fetchPosts, запускає функцію для отримання даних.
Як вже згадувалося, хук надає кілька станів, які можна розпакувати та використовувати для покращення взаємодії з користувачем під час процесу отримання даних. Ці стани включають isLoading, isError та інші.
Для цього додайте наступний код для відображення різних екранів повідомлень на основі поточного стану:
if (isLoading) {
return (<h2>Завантаження...</h2>);
}if (isError) {
return (<h2 className="error-message">{error.message}</h2>);
}
Нарешті, додайте код для елементів JSX, які відображатимуться на сторінці браузера. Цей код також виконує дві інші функції:
- Після отримання публікацій від API, вони зберігаються у змінній data, наданій хуком useQuery, що допомагає керувати станом програми. Потім можна відобразити список публікацій, збережених у цій змінній.
- Додайте дві навігаційні кнопки, “Назад” і “Далі”, які дозволяють користувачам запитувати та відображати додаткові дані з пагінацією.
return (
<div>
<h2 className="header">Пагінація Next.js</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"
>Попередня сторінка</button><button
onClick={() => setPage(prevState => prevState + 1)}
className="next-button"
>Наступна сторінка</button>
</div>
</div>
);
Нарешті, запустіть сервер розробки.
npm run dev
Перейдіть до http://localhost:3000/Pagination у вашому браузері.
Оскільки ви розмістили папку Pagination у каталозі програми, Next.js розглядає її як маршрут, що дозволяє отримати доступ до сторінки за цією URL-адресою.
Нескінченне прокручування створює безперервний перегляд. Прикладом може бути YouTube, який автоматично завантажує та відображає нові відео під час прокручування вниз.
Хук useInfiniteQuery дозволяє реалізувати нескінченне прокручування шляхом отримання даних з сервера сторінками та автоматичного завантаження наступної сторінки даних, коли користувач прокручує вниз.
Для застосування нескінченного прокручування, створіть файл InfiniteScroll/page.js у каталозі src/app. Потім виконайте наступні імпорти:
"use client"
import React, { useRef, useEffect, useState } from 'react';
import { useInfiniteQuery } from '@tanstack/react-query';
import './page.styles.css';
Далі, створіть функціональний React-компонент. Всередині цього компонента, подібно до реалізації пагінації, створіть функцію для отримання публікацій.
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('Не вдалося отримати публікації');
}const data = await response.json();
await new Promise((resolve) => setTimeout(resolve, 2000));
return data;
} catch (error) {
console.error(error);
throw error;
}
};
}
На відміну від реалізації пагінації, цей код вводить затримку у дві секунди під час отримання даних, щоб користувач мав час дослідити поточні дані перед завантаженням нових.
Тепер визначте хук useInfiniteQuery. При першому завантаженні компонента хук отримає першу сторінку даних з сервера. Коли користувач прокручує вниз, хук автоматично отримує наступну сторінку даних та відображає їх в компоненті.
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) : [];
Змінна posts об’єднує усі публікації з різних сторінок в один масив, створюючи зведену версію змінної data, що спрощує відображення окремих публікацій.
Для відстежування прокручування користувача та завантаження додаткових даних, коли користувач наближається до кінця списку, можна визначити функцію, яка використовує Intersection Observer API для виявлення, коли елементи перетинаються з вікном перегляду.
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]);
Нарешті, додайте елементи JSX для відображення публікацій у браузері.
return (
<div>
<h2 className="header">Нескінченне прокручування</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 ? 'Завантаження...' : isLoadingMore ? 'Завантаження ще...' : null}
</div>
</div>
);
Після внесення всіх змін, перейдіть до http://localhost:3000/InfiniteScroll, щоб побачити їх у дії.
TanStack Query: Більше, ніж просто отримання даних
Пагінація та нескінченне прокручування є яскравими прикладами, що демонструють можливості TanStack Query. Простіше кажучи, це універсальна бібліотека для управління даними.
Завдяки широкому спектру функцій можна оптимізувати процеси управління даними вашого застосунку, зокрема ефективно обробляти стан. Разом з іншими завданнями, пов’язаними з даними, ви можете покращити загальну продуктивність ваших веб-додатків, а також покращити взаємодію з користувачем.