TanStack Query'i projenize kurmak için:
npm install @tanstack/react-query
# veya
yarn add @tanstack/react-query
Ö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, 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, 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>
)
}
Sorguları geçersiz kılma ve güncel verileri yeniden çekme:
queryClient.invalidateQueries({ queryKey: ['todos'] })
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()),
})
}
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>
</>
)
}
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 davranışını yapılandırın:
const { data } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
staleTime: 60 * 1000, // 1 dakika
cacheTime: 5 * 60 * 1000, // 5 dakika
})
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)
},
})
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 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>
)
}
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>
)
}
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()
})
2024 © Tüm hakları saklıdır - buraxta.com