خبر و ترفند روز

خبر و ترفند های روز را اینجا بخوانید!

نحوه پیاده سازی پیمایش و صفحه بندی بی نهایت با Next.js و TanStack Query

از این تکنیک ها برای ایجاد رابط های قابل استفاده برای پیمایش مجموعه داده ها استفاده کنید.

اکثر برنامه هایی که توسعه می دهید داده ها را مدیریت می کنند. همانطور که برنامه ها به مقیاس ادامه می دهند، می تواند مقدار زیادی از آن وجود داشته باشد. زمانی که برنامه ها نتوانند حجم زیادی از داده ها را به طور موثر مدیریت کنند، عملکرد ضعیفی دارند.

صفحه بندی و پیمایش بی نهایت دو تکنیک محبوبی هستند که می توانید برای بهینه سازی عملکرد برنامه از آنها استفاده کنید. آن‌ها می‌توانند به شما در مدیریت کارآمدتر داده‌ها و بهبود تجربه کلی کاربر کمک کنند.

صفحه بندی و اسکرول بی نهایت با استفاده از TanStack Query

TanStack Query – اقتباسی از React Query – یک کتابخانه مدیریت دولتی قوی برای برنامه های جاوا اسکریپت است. این یک راه حل کارآمد برای مدیریت وضعیت برنامه، در میان سایر عملکردها، از جمله وظایف مربوط به داده مانند ذخیره سازی، ارائه می دهد.

لپ‌تاپ با کد روی صفحه‌اش روی میز

صفحه بندی شامل تقسیم یک مجموعه داده بزرگ به صفحات کوچکتر است که به کاربران این امکان را می دهد تا با استفاده از دکمه های ناوبری محتوا را در قطعات قابل مدیریت هدایت کنند. در مقابل، اسکرول بی نهایت تجربه مرور پویاتری را ارائه می دهد. زمانی که کاربر پیمایش می کند، داده های جدید به طور خودکار بارگیری و نمایش داده می شوند و نیاز به پیمایش صریح را از بین می برند.

صفحه بندی و پیمایش بی نهایت با هدف مدیریت کارآمد و ارائه مقادیر زیادی از داده ها انجام می شود. انتخاب بین این دو بستگی به نیازهای داده برنامه دارد.

می توانید کد این پروژه را در این مخزن GitHub پیدا کنید.

راه اندازی یک پروژه Next.js

برای شروع، یک پروژه Next.js ایجاد کنید. آخرین نسخه Next.js 13 را نصب کنید که از فهرست برنامه استفاده می کند.

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

بعد، بسته TanStack را با استفاده از npm، مدیر بسته Node در پروژه خود نصب کنید.

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: '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 };

این تنظیمات تضمین می کند که TanStack Query به وضعیت برنامه دسترسی کامل دارد.

مطلب مرتبط:   راهنمای مبتدیان برای انیمیشن SVG با CSS

پیاده سازی صفحه بندی با استفاده از قلاب useQuery

قلاب 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('Failed to fetch posts');
      }

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

  // add the following code here
}

اکنون قلاب useQuery را تعریف کرده و پارامترهای زیر را به عنوان آبجکت مشخص کنید:

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

مقدار KeepPreviousData درست است، که تضمین می‌کند در حین واکشی داده‌های جدید، برنامه داده‌های قبلی را حفظ می‌کند. پارامتر queryKey آرایه ای است که حاوی کلید پرس و جو است، در این مورد، نقطه پایانی و صفحه فعلی که می خواهید داده ها را برای آن واکشی کنید. در نهایت، پارامتر queryFn، fetchPosts، فراخوانی تابع را برای واکشی داده ها راه اندازی می کند.

همانطور که قبلا ذکر شد، قلاب چندین حالت را ارائه می دهد که می توانید آنها را باز کنید، شبیه به نحوه تخریب آرایه ها و اشیاء، و استفاده از آنها برای بهبود تجربه کاربر (پردازش رابط های کاربری مناسب) در طول فرآیند واکشی داده ها. این حالت ها عبارتند از isLoading، isError و غیره.

برای انجام این کار، کد زیر را وارد کنید تا صفحه‌های پیام مختلف بر اساس وضعیت فعلی فرآیند در حال انجام ارائه شود:

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

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

در نهایت، کد عناصر JSX را که در صفحه مرورگر ارائه می‌شوند، اضافه کنید. این کد دو عملکرد دیگر را نیز انجام می دهد:

  • هنگامی که برنامه پست ها را از API واکشی می کند، آنها در متغیر داده ارائه شده توسط قلاب useQuery ذخیره می شوند. این متغیر به مدیریت وضعیت برنامه کمک می کند. سپس می توانید لیست پست های ذخیره شده در این متغیر را نقشه برداری کنید و آنها را در مرورگر رندر کنید.
  • برای افزودن دو دکمه پیمایش، قبلی و بعدی، به کاربران اجازه می دهد تا داده های صفحه بندی شده اضافی را بر اساس آن پرس و جو کرده و نمایش دهند.

  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>
  );

در نهایت، سرور توسعه را راه اندازی کنید.

npm run dev

سپس، در یک مرورگر به http://localhost:3000/Pagination بروید.

مطلب مرتبط:   دستکاری زمان و تاریخ در برنامه های Go

مثال صفحه‌بندی پرس و جوی Tanstack در برنامه Next.js

از آنجایی که پوشه Pagination را در فهرست برنامه گنجانده اید، Next.js آن را به عنوان یک مسیر در نظر می گیرد و به شما امکان می دهد به صفحه در آن URL دسترسی داشته باشید.

اسکرول بی نهایت با استفاده از قلاب useInfiniteQuery

پیمایش بی‌نهایت یک تجربه مرور یکپارچه را فراهم می‌کند. یک مثال خوب یوتیوب است که ویدیوهای جدید را به صورت خودکار واکشی می کند و در حین اسکرول کردن، آنها را نمایش می دهد.

قلاب 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('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;
    }
  };

  // add the following code here
}

برخلاف پیاده‌سازی صفحه‌بندی، این کد یک تاخیر دو ثانیه‌ای را هنگام واکشی داده‌ها معرفی می‌کند تا به کاربر اجازه دهد تا داده‌های فعلی را در حالی که پیمایش می‌کند تا بازیابی مجموعه جدیدی از داده‌ها را آغاز کند، کاوش کند.

مطلب مرتبط:   ایجاد یک پروژه TypeScript از ابتدا

حال، قلاب 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 همه پست‌ها را از صفحات مختلف در یک آرایه واحد ترکیب می‌کند و در نتیجه یک نسخه مسطح از متغیر داده ایجاد می‌شود. این به شما این امکان را می دهد که به راحتی پست های جداگانه را نقشه برداری و رندر کنید.

برای ردیابی اسکرول‌های کاربر و بارگیری داده‌های بیشتر زمانی که کاربر به انتهای لیست نزدیک است، می‌توانید تابعی را تعریف کنید که از Intersection Observer API برای تشخیص زمان تقاطع عناصر با viewport استفاده می‌کند.

  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">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>
  );

هنگامی که همه تغییرات را انجام دادید، از http://localhost:3000/InfiniteScroll دیدن کنید تا آنها را در عمل ببینید.

TanStack Query: فراتر از واکشی داده ها

صفحه بندی و اسکرول بی نهایت نمونه های خوبی هستند که قابلیت های TanStack Query را برجسته می کنند. به زبان ساده، این یک کتابخانه مدیریت داده همه جانبه است.

با مجموعه گسترده ای از ویژگی های آن، می توانید فرآیندهای مدیریت داده برنامه خود را ساده کنید، از جمله مدیریت کارآمد وضعیت. در کنار سایر وظایف مرتبط با داده، می توانید عملکرد کلی برنامه های کاربردی وب خود و همچنین تجربه کاربری را بهبود بخشید.