"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > إنشاء صفحة موجزة باستخدام React Query

إنشاء صفحة موجزة باستخدام React Query

تم النشر بتاريخ 2024-11-09
تصفح:786

Building a Feed Page Using React Query

الهدف

في هذه المقالة، سنستكشف كيفية إنشاء صفحة موجز باستخدام React Query!

إليك ما سنقوم بإنشائه:

لن تغطي هذه المقالة كل خطوة وتفاصيل تتعلق بإنشاء التطبيق.
وبدلاً من ذلك، سنركز على الميزات الرئيسية، وتحديدًا وظائف "التمرير اللانهائي" و"التمرير إلى الأعلى".
إذا كنت مهتمًا بمراجعة التنفيذ بالكامل، فيمكنك العثور على قاعدة التعليمات البرمجية الكاملة في مستودع GitHub هذا.

إعداد التطبيق

أولاً، سنقوم بإنشاء تطبيق React الخاص بنا باستخدام Vite باستخدام الأمر التالي:

npm create vite@latest feed-page-rq -- --template react-ts

وسوف نقوم بتثبيت التبعيات المطلوبة، axios و react-query:

npm install axios @tanstack/react-query@4

نحتاج أيضًا إلى محاكاة خادم RESTful، لذلك سنستخدم json-server، والذي يسمح لنا بمحاكاة الواجهة الخلفية من خلال توفير نقاط نهاية API وهمية لتطبيق React الخاص بنا.

سنعمل مع كيان منشور يتضمن السمات التالية:

{
  "id": "1",
  "title": "Sample Post Title",
  "body": "This is a sample post body",
  "userId": "2",
  "createdAt": 1728334799169 // date timestamp
}

بمجرد إعداد الخادم، سنقوم بتشغيله باستخدام:

npx json-server --watch db.json

تنفيذ "التمرير اللانهائي"

آلية ميزة "التمرير اللانهائي" واضحة ومباشرة:
عندما يقوم المستخدم بالتمرير عبر قائمة المنشورات ويقترب من أسفل الحاوية، سيبحث React Query عن الدفعة التالية من المنشورات. تتكرر هذه العملية حتى لا يكون هناك المزيد من المشاركات للتحميل.

نتحقق مما إذا كان المستخدم بالقرب من الأسفل عن طريق إضافة موضع التمرير الحالي (scrollTop) إلى ارتفاع الشاشة المرئي (clientHeight) ومقارنة هذا المجموع مع الارتفاع الإجمالي للحاوية (ارتفاع التمرير).
إذا كان المجموع أكبر من أو يساوي إجمالي ارتفاع الحاوية، فإننا نطلب من React Query جلب الصفحة التالية.

  const { scrollTop, scrollHeight, clientHeight } = elemRef.current;
  if(scrollTop   clientHeight >= scrollHeight) {
      fetchNextPage();
  }

الخطوة 1: تكوين useInfiniteQuery

أولاً، سنقوم بإنشاء رابط مخصص لتغليف useInfiniteQuery الخاص بـ React Query.

ضمن الرابط المخصص، نقوم بتكوين الاستعلام لجلب المنشورات صفحة تلو الأخرى، مع تحديد رقم الصفحة الأولي والوظيفة التي تسترد الصفحات التالية:

import { QueryFunctionContext, useInfiniteQuery } from "@tanstack/react-query";
import axios from "axios";

const URL = "http://localhost:3000";
const POSTS = "posts";

export const fetchInfinitePosts = async ({
  pageParam,
}: QueryFunctionContext) => {
  const result = await axios.get(
    `${URL}/${POSTS}?_sort=-createdAt&_page=${pageParam}&_per_page=10`,
  );
  return result.data;
};

export const useInfinitePosts = () => {
  return useInfiniteQuery({
    queryKey: [POSTS],
    queryFn: fetchInfinitePosts,
    initialPageParam: 1,
    getNextPageParam: (lastPage) => lastPage.next,
  });
};

الخطوة 2: عرض المشاركات في PostList

الآن، سوف نستخدم الرابط المخصص في المكون الخاص بنا لعرض قائمة المنشورات.
للقيام بذلك، نقوم أولاً بتكرار الصفحات ثم نكررها على المنشورات داخل كل صفحة لعرضها.

import { useInfinitePosts } from './hooks/useInfinitePosts';

const PostList = () => {
  const { data: postLists } = useInfinitePosts();

  return (
    
{postLists?.pages.map((page) => page.data.map(post => (

{post.title}

{post.body}

)) )}
); }; export default PostList;

الخطوة 3: تنفيذ سلوك التمرير اللانهائي

لتنفيذ سلوك التمرير اللانهائي، نحتاج إلى إضافة مستمع لحدث التمرير إلى الحاوية التي يتم عرض المنشورات فيها. يقوم مستمع الحدث بتشغيل وظيفة onScroll، التي تتحقق مما إذا كان المستخدم بالقرب من الجزء السفلي من الحاوية، وإذا كان الأمر كذلك، فإنه يستدعي fetchNextPage لتحميل المزيد من المحتوى.

import React, { useRef, useEffect } from 'react';
import { useInfinitePosts } from './hooks/useInfinitePosts';

const PostList = () => {
  const { data: postLists, fetchNextPage } = useInfinitePosts();
  const elemRef = useRef(null);

  const onScroll = useCallback(() => {
    if (elemRef.current) {
      const { scrollTop, scrollHeight, clientHeight } = elemRef.current;
      const isNearBottom = scrollTop   clientHeight >= scrollHeight;
      if(isNearBottom) {
          fetchNextPage();
      }
    }
  }, [fetchNextPage]);

  useEffect(() => {
    const innerElement = elemRef.current;
  
    if (innerElement) {
      innerElement.addEventListener("scroll", onScroll);

      return () => {
        innerElement.removeEventListener("scroll", onScroll);
      };
    }
  }, [onScroll]);

  return (
    
{postLists?.pages.map((page, i) => page.data.map(post => (

{post.title}

{post.body}

)) )}
); }; export default PostList;

تنفيذ "التمرير إلى الأعلى"

بعد ذلك، سنقوم بإنشاء زر "التمرير إلى الأعلى" الذي يظهر عند إضافة مشاركة جديدة. يتيح هذا الزر للمستخدم العودة بسرعة إلى الأعلى لرؤية آخر تحديث.
وبما أن المشاركات يتم فرزها حسب تاريخ الإنشاء، فإن أي مشاركة تمت إضافتها حديثًا ستظهر في أعلى القائمة.
سيتم بناء منطق الميزة لدينا على أساس هذه الفرضية.

الخطوة 1: إنشاء استعلام لـ prevNewestPost

نبدأ بإنشاء استعلام جديد لجلب آخر منشور تم إنشاؤه وتخزينه مؤقتًا. سوف نسمي هذا المنشور بـ prevNewestPost.
نريد أن يظل prevNewestPost متأخرًا ببضع خطوات، أو على الأكثر، يطابق المنشور الأول في القائمة. لذلك، سوف نتحكم يدويًا في إعادة جلبه.
سوف نحقق ذلك من خلال وضع تمكين: خطأ في خيارات الاستعلام.

export const fetchNewestPost = async () => {
  const result = await axios.get(`${URL}/${POSTS}?_sort=-createdAt`);
  return result.data[0];
};

export const useNewestPost = () => {
  return useQuery({
    queryKey: [POSTS, "newest"],
    queryFn: () => fetchNewestPost(),
    enabled: false,
  });
};

الخطوة 2: قارن prevNewestPost مع المشاركة الأولى

باستخدام React Query، يتم تحديث قائمة المنشورات تلقائيًا في أحداث محددة. (إليك رابط التوثيق للحصول على قائمة كاملة بهذه الأحداث.)
سوف نستخدم هذه القائمة المحدثة لتحديد وقت عرض زر "التمرير إلى الأعلى" من خلال مقارنة prevNewestPost بالمنشور الأول.
إذا كانت مختلفة، فهذا يشير إلى أنه قد تمت إضافة مشاركة جديدة، لذلك سيظهر زر "التمرير إلى الأعلى".

setIsShowButton(postLists?.pages[0].data[0].id !== prevNewestPost?.id);

الخطوة 3: إخفاء الزر عندما يكون المؤشر في الأعلى

لا ينبغي أن نظهر زر "التمرير إلى الأعلى" عندما يكون المستخدم في أعلى حاوية قائمة المشاركات.
لذلك، عندما يصل المستخدم إلى الأعلى، نحتاج إلى إعادة مزامنة NewestPost السابق مع آخر مشاركة حالية عن طريق تشغيل إعادة جلب الاستعلام.

  const { data: prevNewestPost, refetch } = useNewestPost();
  const [isShowButton, setIsShowButton] = useState(false);
  
  useEffect(() => {
    if (!isNearTop) {
      setIsShowButton(postLists?.pages[0].data[0].id !== prevNewestPost?.id);
    } else {
      setIsShowButton(false);
      refetch();
    }
  }, [postLists, prevNewestPost, isNearTop]);

الخطوة 4: إنشاء زر التمرير إلى الأعلى

سيؤدي النقر فوق زر ToTopBtn إلى التمرير إلى أعلى القائمة، مما يؤدي إلى تشغيل المنطق الموجود لإخفاء الزر وإعادة جلب البيانات لمزامنة المنشور السابق مع المنشور الأول في القائمة.

import { RefObject } from "react";

type ToTopBtnProps = {
  elemRef: RefObject;
};

export default function ToTopBtn({ elemRef }: ToTopBtnProps) {
  return (
    
         
  ); }

الخطوة 5: الاختبار عن طريق إضافة مشاركات جديدة

لاختبار وظيفة زر "التمرير إلى الأعلى"، نحتاج إلى إضافة منشورات جديدة إلى الموجز.
لهذا، سنستخدم useMutation من React Query لإضافة منشور جديد إلى الخادم وإعادة التحقق من قائمة النشرات المخزنة مؤقتًا بعد كل تغيير.
سنقوم بإعداد طفرة تسمح لنا بإنشاء منشور جديد يحتوي على بيانات عشوائية عندما ينقر المستخدم على زر.

export const savePost = async (post: NewPostData) =>
  axios.post(`${URL}/${POSTS}`, post);

export const useAddPost = () => {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: savePost,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: [POSTS] });
    },
  });
};
export default function AddNewPostBtn() {
  const mutation = useAddPost();

  return (
    
         
  );

خاتمة

في هذا البرنامج التعليمي، استكشفنا قوة React Query من خلال حالة استخدام حقيقية، مع تسليط الضوء على قدرتها على مساعدة المطورين في بناء واجهات ديناميكية تعمل على تحسين تجربة المستخدم.

بيان الافراج تم نشر هذه المقالة على: https://dev.to/mohamed_hammi/build-a-feed-page-using-react-query-1nbi?1 إذا كان هناك أي انتهاك، يرجى الاتصال بـ [email protected] لحذفه
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3