logo
eng-flag

TanStack Query Notları ve İpuçları

İçindekiler

  1. Kurulum
  2. Temel Kullanım
  3. Sorgular
  4. Mutasyonlar
  5. Sorgu Geçersiz Kılma
  6. Ön Yükleme
  7. Sonsuz Sorgular
  8. Bağımlı Sorgular
  9. Önbellekleme ve Geçerlilik Süresi
  10. Hata Yönetimi
  11. İyimser Güncellemeler
  12. Sayfalandırma
  13. Sunucu Tarafı Render (SSR)
  14. Test Etme
  15. En İyi Uygulamalar

Kurulum

TanStack Query'i projenize kurmak için:

npm install @tanstack/react-query
# veya
yarn add @tanstack/react-query

Temel Kullanım

Öncelikle uygulamanızı QueryClientProvider ile sarmalayın:

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

const queryClient = new QueryClient()

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      {/* Uygulama bileşenleriniz */}
    </QueryClientProvider>
  )
}

Sorgular

Sorgular, sunucudan veri çekmek için kullanılır. İşte basit bir örnek:

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

function GetTodos() {
  const { isLoading, error, data } = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('https://api.example.com/todos').then(res => res.json()),
  })

  if (isLoading) return 'Yükleniyor...'
  if (error) return 'Bir hata oluştu: ' + error.message

  return (
    <ul>
      {data.map(todo => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  )
}

Mutasyonlar

Mutasyonlar, veri oluşturmak/güncellemek/silmek için kullanılır:

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

function AddTodo() {
  const mutation = useMutation({
    mutationFn: newTodo => {
      return fetch('https://api.example.com/todos', {
        method: 'POST',
        body: JSON.stringify(newTodo),
      })
    },
    onSuccess: () => {
      // Geçersiz kılma ve yeniden çekme
      queryClient.invalidateQueries({ queryKey: ['todos'] })
    },
  })

  return (
    <form onSubmit={(e) => {
      e.preventDefault()
      mutation.mutate({ title: 'Yeni Todo' })
    }}>
      <button type="submit">Todo Ekle</button>
    </form>
  )
}

Sorgu Geçersiz Kılma

Sorguları geçersiz kılma ve güncel verileri yeniden çekme:

queryClient.invalidateQueries({ queryKey: ['todos'] })

Ön Yükleme

Verileri ihtiyaç duymadan önce yükleyin:

const prefetchTodos = async () => {
  await queryClient.prefetchQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('https://api.example.com/todos').then(res => res.json()),
  })
}

Sonsuz Sorgular

Sayfalandırma veya sonsuz kaydırma için:

import { useInfiniteQuery } from '@tanstack/react-query'

function InfiniteTodos() {
  const {
    data,
    error,
    fetchNextPage,
    hasNextPage,
    isFetching,
    isFetchingNextPage,
    status,
  } = useInfiniteQuery({
    queryKey: ['todos'],
    queryFn: ({ pageParam = 0 }) =>
      fetch(`https://api.example.com/todos?page=${pageParam}`).then(res => res.json()),
    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
  })

  return status === 'loading' ? (
    <p>Yükleniyor...</p>
  ) : status === 'error' ? (
    <p>Hata: {error.message}</p>
  ) : (
    <>
      {data.pages.map((group, i) => (
        <React.Fragment key={i}>
          {group.map(todo => (
            <p key={todo.id}>{todo.title}</p>
          ))}
        </React.Fragment>
      ))}
      <button
        onClick={() => fetchNextPage()}
        disabled={!hasNextPage || isFetchingNextPage}
      >
        {isFetchingNextPage
          ? 'Daha Fazla Yükleniyor...'
          : hasNextPage
          ? 'Daha Fazla Yükle'
          : 'Yükleyecek Başka Bir Şey Yok'}
      </button>
      <div>{isFetching && !isFetchingNextPage ? 'Veriler Alınıyor...' : null}</div>
    </>
  )
}

Bağımlı Sorgular

Bir sorgu başka birine bağlı olduğunda:

function UserProjects() {
  const { data: user } = useQuery({
    queryKey: ['user', userId],
    queryFn: () => fetchUser(userId),
  })

  const { data: projects } = useQuery({
    queryKey: ['projects', user?.id],
    queryFn: () => fetchProjects(user.id),
    enabled: !!user,
  })

  // ...
}

Önbellekleme ve Geçerlilik Süresi

Önbellekleme davranışını yapılandırın:

const { data } = useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos,
  staleTime: 60 * 1000, // 1 dakika
  cacheTime: 5 * 60 * 1000, // 5 dakika
})

Hata Yönetimi

Sorgulardaki hataları yönetin:

const { isError, error } = useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos,
  retry: 3, // Başarısız olana kadar 3 kez dene
  onError: (error) => {
    console.error('Bir hata oluştu:', error)
  },
})

İyimser Güncellemeler

Sunucu onayı olmadan UI'yi iyimser bir şekilde güncelleyin:

const queryClient = useQueryClient()

const mutation = useMutation({
  mutationFn: updateTodo,
  onMutate: async (newTodo) => {
    await queryClient.cancelQueries({ queryKey: ['todos', newTodo.id] })
    const previousTodo = queryClient.getQueryData(['todos', newTodo.id])
    queryClient.setQueryData(['todos', newTodo.id], newTodo)
    return { previousTodo }
  },
  onError: (err, newTodo, context) => {
    queryClient.setQueryData(['todos', newTodo.id], context.previousTodo)
  },
  onSettled: (newTodo) => {
    queryClient.invalidateQueries({ queryKey: ['todos', newTodo.id] })
  },
})

Sayfalandırma

Sayfalandırma uygulayın:

function PaginatedTodos() {
  const [page, setPage] = useState(1)
  const { data, isLoading, isPreviousData } = useQuery({
    queryKey: ['todos', page],
    queryFn: () => fetchTodos(page),
    keepPreviousData: true,
  })

  return (
    <div>
      {isLoading ? (
        <div>Yükleniyor...</div>
      ) : (
        <ul>
          {data.todos.map(todo => (
            <li key={todo.id}>{todo.title}</li>
          ))}
        </ul>
      )}
      <button
        onClick={() => setPage(old => Math.max(old - 1, 1))}
        disabled={page === 1}
      >
        Önceki Sayfa
      </button>
      <button
        onClick={() => setPage(old => (!isPreviousData && data.hasMore ? old + 1 : old))}
        disabled={isPreviousData || !data?.hasMore}
      >
        Sonraki Sayfa
      </button>
    </div>
  )
}

Sunucu Tarafı Render (SSR)

SSR için yapılandırma:

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { Hydrate } from '@tanstack/react-query/hydration'
import { dehydrate } from '@tanstack/react-query'

function App() {
  const queryClient = new QueryClient()
  return (
    <QueryClientProvider client={queryClient}>
      <Hydrate state={dehydrate(queryClient)}>
        {/* Uygulama bileşenleriniz */}
      </Hydrate>
    </QueryClientProvider>
  )
}

Test Etme

Sorguları test etme:

import { render, screen } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient()

function TestComponent() {
  const { data } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodos,
  })

  return <div>{data ? data.length : 'Yükleniyor...'}</div>
}

test('TestComponent renders data', async () => {
  render(
    <QueryClientProvider client={queryClient}>
      <TestComponent />
    </QueryClientProvider>
  )

  expect(await screen.findByText('Yükleniyor...')).toBeInTheDocument()
})

En İyi Uygulamalar

  • İyi bir yapı: Sorgu ve mutasyonları iyi bir şekilde yönetmek için uygun bir yapı oluşturun.
  • Performans: Performansı artırmak için veri önbellekleme ve sorgu geçersiz kılma özelliklerini kullanın.
  • Hata Yönetimi: Hataları etkili bir şekilde yönetin ve kullanıcıyı bilgilendirin.
  • Test: Bileşenlerinizi test edin ve sorgu/mutasyon davranışını doğrulayın.
  • Dokümantasyon: Kütüphanenin belgelerini okuyun ve en iyi uygulamalar için resmi dokümantasyonu takip edin.

2024 © Tüm hakları saklıdır - buraxta.com