TanStack Query ל-React: שמירה במטמון, מוטציות, SSR

מפתחי React מבזבזים זמן רב מדי על קוד טיפול בנתונים שחוזר על עצמו, מה שמסיח את הדעת מהלוגיקה העסקית. אנו מגדירים את TanStack Query כדי להפוך caching, mutations ו-SSR לאוטומטיים, וחוסכים לך מהשגרה. הצוות שלנו מספק פתרון turnkey—מביקורת ועד תמיכה—ומבטיח פתרון אמין וניתן להרחבה.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
TanStack Query ל-React: שמירה במטמון, מוטציות, SSR
בינוני
מ- 1 יום עד 3 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113
  • פיתוח אתר עבור SBH Partners
    פיתוח אתר עבור SBH Partners
    1201
  • פיתוח אתר עבור Red Pear
    פיתוח אתר עבור Red Pear
    619

מבוא

מפתחי React כותבים כל הזמן קוד תבניתי לטיפול בנתונים: useEffect, useState, reducers. כל מסך חדש משכפל את הלוגיקה של טעינה, שמירה במטמון ועדכון. כתוצאה מכך, 60–70% מהקוד הוא קוד תבניתי שמסיח את הדעת מהלוגיקה העסקית. בפרויקט אחד, החלפנו את Redux Thunk ב-TanStack Query, קיצצנו את הקוד ב-70%, והפחתנו באגים פי שלושה.

TanStack Query (לשעבר React Query) היא ספרייה לניהול state של השרת. היא מטפלת במטמון, עדכונים ברקע, דדופליקציה של בקשות, פאג'ינציה, מוטציות עם עדכונים אופטימיים, וטעינה מוקדמת. התוצאה: קוד שקשור לנתונים קטן ב-60–70%, ובאגים יורדים פי 2–3. אנו מגדירים את TanStack Query מאז ימיה הראשונים, עם למעלה מ-50 פרויקטים שהושלמו. אנו מבטיחים פעולה יציבה וחיסכון של 30–50% בזמן. צרו קשר לקבלת הגדרה וקבלו ארכיטקטורת נתונים מלאה תוך ימים.

גישה קוד תבניתי מורכבות מדרגיות
Redux Thunk גבוה גבוהה בינונית
RTK Query בינוני בינונית גבוהה
TanStack Query נמוך נמוכה גבוהה
SWR נמוך נמוכה בינונית

בעיות ש-TanStack Query פותר

ניהול מטמון ידני: ללא הספרייה, צריך לסנכרן בקשות ידנית, לטפל בטעינה ובשגיאות. TanStack Query שומרת נתונים במטמון אוטומטית, מבצעת דדופליקציה של בקשות מקבילות, ומעדכנת את המטמון במוטציות. נקודת כאב נוספת היא פסילת מטמון. עם מפתחות היררכיים, ניתן לפסול את כל הרשימות הקשורות בפקודה אחת מבלי לגעת בפרטים.

איך להגדיר QueryClient עם פרמטרים אופטימליים

reducers הוא האובייקט המרכזי שמנהל את כל השאילתות. התצורה שלו משפיעה על הביצועים. הנה ערכים מומלצים:

פרמטר ברירת מחדל מומלץ למה
staleTime 0 5 * 60 * 1000 נתונים נחשבים טריים למשך 5 דקות; אין טעינה מחדש בכל mount
gcTime 5 * 60 * 1000 10 * 60 * 1000 המטמון נשמר 10 דקות לאחר הסרת הפניות (לשעבר cacheTime)
retry 3 2 ניסיונות חוזרים בשגיאה – מספיק לכשלים זמניים
refetchOnWindowFocus false true עדכון נתונים אוטומטי בחזרה לטאב

דוגמה לאתחול בסיסי:

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000,
      gcTime: 10 * 60 * 1000,
      retry: 2,
      refetchOnWindowFocus: true,
    },
    mutations: {
      retry: 0,
    },
  },
})

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Router />
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  )
}

אם הפרויקט משתמש ב-Next.js App Router, אנו מוסיפים טעינה מוקדמת בצד השרת באמצעות import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 5 * 60 * 1000, gcTime: 10 * 60 * 1000, retry: 2, refetchOnWindowFocus: true, }, mutations: { retry: 0, }, }, }) function App() { return ( <QueryClientProvider client={queryClient}> <Router /> <ReactQueryDevtools initialIsOpen={false} /> </QueryClientProvider> ) } ו-dehydrate.

למה מפתחות שאילתה הם המפתח לפסילה יעילה

מפתחות שאילתה הם מזהים ייחודיים לשאילתה. מבנה המפתח קובע כיצד המטמון נפסל לאחר מוטציות. אנו משתמשים בגישה היררכית:

export const queryKeys = {
  products: {
    all: ['products'] as const,
    lists: () => [...queryKeys.products.all, 'list'] as const,
    list: (filters: ProductFilters) => [...queryKeys.products.lists(), filters] as const,
    details: () => [...queryKeys.products.all, 'detail'] as const,
    detail: (id: string) => [...queryKeys.products.details(), id] as const,
  },
  users: {
    all: ['users'] as const,
    me: () => [...queryKeys.users.all, 'me'] as const,
    profile: (id: string) => [...queryKeys.users.all, 'profile', id] as const,
  },
}

זה מאפשר לפסול את כל רשימות המוצרים בפקודה אחת מבלי לגעת בפרטים.

ה-Hooks המרכזיים: useQuery, useMutation, useInfiniteQuery

ה-hook הבסיסי לטעינת נתונים הוא HydrationBoundary. הוא מחזיר מצב טעינה, שגיאה ונתונים. עבור UI קריטי, השתמשו ב-export const queryKeys = { products: { all: ['products'] as const, lists: () => [...queryKeys.products.all, 'list'] as const, list: (filters: ProductFilters) => [...queryKeys.products.lists(), filters] as const, details: () => [...queryKeys.products.all, 'detail'] as const, detail: (id: string) => [...queryKeys.products.details(), id] as const, }, users: { all: ['users'] as const, me: () => [...queryKeys.users.all, 'me'] as const, profile: (id: string) => [...queryKeys.users.all, 'profile', id] as const, }, } עם React Suspense.

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'

export function useProducts(filters: ProductFilters) {
  return useQuery({
    queryKey: queryKeys.products.list(filters),
    queryFn: () => api.get<Product[]>('/products', { params: filters }),
    placeholderData: (prev) => prev,
  })
}

export function useUpdateProduct() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: ({ id, data }: { id: string; data: UpdateProductDto }) =>
      api.patch<Product>(`/products/${id}`, data),
    onMutate: async ({ id, data }) => {
      await queryClient.cancelQueries({ queryKey: queryKeys.products.detail(id) })
      const previous = queryClient.getQueryData<Product>(queryKeys.products.detail(id))
      queryClient.setQueryData(queryKeys.products.detail(id), (old: Product) => ({ ...old, ...data }))
      return { previous }
    },
    onError: (_, { id }, context) => {
      if (context?.previous) {
        queryClient.setQueryData(queryKeys.products.detail(id), context.previous)
      }
    },
    onSettled: (_, __, { id }) => {
      queryClient.invalidateQueries({ queryKey: queryKeys.products.detail(id) })
    },
  })
}

לגלילה אינסופית – useQuery:

export function useInfiniteProducts(filters: Omit<ProductFilters, 'page'>) {
  return useInfiniteQuery({
    queryKey: queryKeys.products.list(filters),
    queryFn: ({ pageParam }) =>
      api.get<PaginatedResponse<Product>>('/products', {
        params: { ...filters, page: pageParam, pageSize: 20 },
      }),
    initialPageParam: 1,
    getNextPageParam: (lastPage) =>
      lastPage.hasNextPage ? lastPage.page + 1 : undefined,
  });
}

לפאג'ינציה פשוטה, השתמשו ב-useSuspenseQuery בתוך import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' export function useProducts(filters: ProductFilters) { return useQuery({ queryKey: queryKeys.products.list(filters), queryFn: () => api.get<Product[]>('/products', { params: filters }), placeholderData: (prev) => prev, }) } export function useUpdateProduct() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ id, data }: { id: string; data: UpdateProductDto }) => api.patch<Product>(`/products/${id}`, data), onMutate: async ({ id, data }) => { await queryClient.cancelQueries({ queryKey: queryKeys.products.detail(id) }) const previous = queryClient.getQueryData<Product>(queryKeys.products.detail(id)) queryClient.setQueryData(queryKeys.products.detail(id), (old: Product) => ({ ...old, ...data })) return { previous } }, onError: (_, { id }, context) => { if (context?.previous) { queryClient.setQueryData(queryKeys.products.detail(id), context.previous) } }, onSettled: (_, __, { id }) => { queryClient.invalidateQueries({ queryKey: queryKeys.products.detail(id) }) }, }) } .

איך ליישם עדכונים אופטימיים ללא כאב

עדכון אופטימי: ה-UI משתנה לפני שהשרת מגיב. TanStack Query עושה זאת בקלות: ב-useInfiniteQuery עדכנו את המטמון, ב-export function useInfiniteProducts(filters: Omit<ProductFilters, 'page'>) { return useInfiniteQuery({ queryKey: queryKeys.products.list(filters), queryFn: ({ pageParam }) => api.get<PaginatedResponse<Product>>('/products', { params: { ...filters, page: pageParam, pageSize: 20 } }), initialPageParam: 1, getNextPageParam: (lastPage) => (lastPage.hasNextPage ? lastPage.page + 1 : undefined), }) } בצעו rollback. הדוגמה למעלה עם keepPreviousData מציגה טכניקה זו. המשתמש רואה משוב מיידי, ובשגיאה הנתונים חוזרים למצבם המקורי.

טעינה מוקדמת ו-SSR עם Next.js

טעינה מוקדמת טוענת נתונים לפני ניווט לעמוד. לדוגמה, ב-hover על קישור:

function ProductLink({ id }: { id: string }) {
  const queryClient = useQueryClient()
  return (
    <Link
      to={`/products/${id}`}
      onMouseEnter={() => {
        queryClient.prefetchQuery({
          queryKey: queryKeys.products.detail(id),
          queryFn: () => api.get<Product>(`/products/${id}`),
          staleTime: 60_000,
        })
      }}
    >
      Перейти
    </Link>
  )
}

עבור SSR ב-Next.js App Router, השתמשו ב-placeholderData ו-onMutate בצד השרת:

import { HydrationBoundary, QueryClient, dehydrate } from '@tanstack/react-query'
export default async function ProductsPage() {
  const queryClient = new QueryClient()
  await queryClient.prefetchQuery({
    queryKey: queryKeys.products.lists(),
    queryFn: () => fetchProductsServer(),
  })
  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <ProductList />
    </HydrationBoundary>
  )
}

פרטים נוספים בתיעוד הרשמי של TanStack Query.

מה כלול בשירות שלנו

אנו מגדירים את TanStack Query לפרויקט שלכם:

  • התקנה והגדרת QueryClient המותאמת ל-API שלכם.
  • עיצוב מבנה מפתחות שאילתה היררכי לפסילה קלה.
  • כתיבת hooks מותאמים לכל ה-endpoints: useQuery, useMutation, useInfiniteQuery.
  • יישום עדכונים אופטימיים לטפסים (לייקים, תגובות, עריכה).
  • הגדרת טעינה מוקדמת ואינטגרציה עם SSR/Next.js.
  • חיבור DevTools לניפוי באגים.
  • תיעוד והדרכת צוות.

תהליך:

  1. ניתוח – ביקורת על הסטאק הנוכחי וה-API, זיהוי נקודות אינטגרציה.
  2. עיצוב – תכנית מפתחות שאילתה, בחירת אסטרטגיית מטמון.
  3. יישום – כתיבת hooks, בדיקת מוטציות, אופטימיזציה.
  4. בדיקות – אימות פסילה, הרשאות, מקרי קצה.
  5. פריסה – השקה, ניטור באמצעות DevTools.

לוח זמנים: בין 2 ל-5 ימים תלוי במספר ה-endpoints. העלות מחושבת באופן אישי. החיסכון בתחזוקה עתידית מחזיר את ההשקעה תוך שבועות.

צרו קשר לייעוץ – נעזור לכם ליישם את TanStack Query ולקצץ את זמן הפיתוח ב-30–50%. קבלו ארכיטקטורת נתונים מוכנה תוך ימים.