Documentation
Framework
Version
Debouncer API Reference
Throttler API Reference
Rate Limiter API Reference
Queue API Reference
Batcher API Reference

React Example: React Query Throttled Prefetch

import React, { useEffect } from 'react' import ReactDOM from 'react-dom/client' import { QueryClient, QueryClientProvider, useQuery, } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' import { useThrottledValue } from '@tanstack/react-pacer' // Fetch all posts const fetchPosts = async () => { const response = await fetch('https://jsonplaceholder.typicode.com/posts') return response.json() } // Fetch a single post const fetchPost = async (id: number) => { await new Promise((resolve) => setTimeout(resolve, 1000)) // Simulate a slow response const response = await fetch( `https://jsonplaceholder.typicode.com/posts/${id}`, ) return response.json() } function PostList({ setSelectedPostId, }: { setSelectedPostId: (id: number) => void }) { // Simple query that fetches all posts const { data: posts, isLoading } = useQuery({ queryKey: ['posts'], queryFn: fetchPosts, }) // keep track of the hovered post id that could be prefetched const [currentHoveredPostId, setCurrentHoveredPostId] = React.useState< number | null >(null) // throttle the hovered post id to avoid excessive prefetches const [throttledHoveredPostId] = useThrottledValue(currentHoveredPostId, { wait: 100, // adjust this value to see the difference }) // perform the prefetch when the throttled hovered post id changes useEffect(() => { if (throttledHoveredPostId) { queryClient.ensureQueryData({ queryKey: ['post', throttledHoveredPostId], queryFn: () => fetchPost(throttledHoveredPostId), }) } }, [throttledHoveredPostId]) const handleMouseEnter = (postId: number) => { setCurrentHoveredPostId(postId) // update the hovered post id } if (isLoading) return <div>Loading posts...</div> return ( <div> <h2>Posts</h2> <ul style={{ margin: 0, padding: 0 }}> {posts?.map((post: { id: number; title: string }) => ( <li key={post.id} style={{ margin: '2px 0' }}> <a href={`#post-${post.id}`} onMouseEnter={() => handleMouseEnter(post.id)} onClick={() => setSelectedPostId(post.id)} style={{ display: 'block', padding: '4px', cursor: 'pointer' }} > {post.title} </a> </li> ))} </ul> </div> ) } function PostDetail({ postId }: { postId: number }) { const { data: post, isLoading } = useQuery({ queryKey: ['post', postId], queryFn: () => fetchPost(postId), }) if (isLoading) return <div>Loading post...</div> return ( <div> <h3>{post?.title}</h3> <p>{post?.body}</p> </div> ) } function App() { const [selectedPostId, setSelectedPostId] = React.useState<number | null>( null, ) return ( <div className="App" style={{ maxWidth: '800px', margin: '0 auto', padding: '20px' }} > <h1>TanStack Pacer/Query Throttled Prefetch Example</h1> <p>Hover over a post title to prefetch its content</p> <p> This example shows how to prefetch a query when the user hovers over a post. </p> <p> The throttled query key is created after a throttle to avoid excessive prefetches. </p> <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }} > <PostList setSelectedPostId={setSelectedPostId} /> {selectedPostId && <PostDetail postId={selectedPostId} />} </div> </div> ) } const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 10_000, }, }, }) const root = ReactDOM.createRoot(document.getElementById('root')!) root.render( <QueryClientProvider client={queryClient}> <App /> <ReactQueryDevtools initialIsOpen={false} /> </QueryClientProvider>, ) 
import React, { useEffect } from 'react' import ReactDOM from 'react-dom/client' import { QueryClient, QueryClientProvider, useQuery, } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' import { useThrottledValue } from '@tanstack/react-pacer' // Fetch all posts const fetchPosts = async () => { const response = await fetch('https://jsonplaceholder.typicode.com/posts') return response.json() } // Fetch a single post const fetchPost = async (id: number) => { await new Promise((resolve) => setTimeout(resolve, 1000)) // Simulate a slow response const response = await fetch( `https://jsonplaceholder.typicode.com/posts/${id}`, ) return response.json() } function PostList({ setSelectedPostId, }: { setSelectedPostId: (id: number) => void }) { // Simple query that fetches all posts const { data: posts, isLoading } = useQuery({ queryKey: ['posts'], queryFn: fetchPosts, }) // keep track of the hovered post id that could be prefetched const [currentHoveredPostId, setCurrentHoveredPostId] = React.useState< number | null >(null) // throttle the hovered post id to avoid excessive prefetches const [throttledHoveredPostId] = useThrottledValue(currentHoveredPostId, { wait: 100, // adjust this value to see the difference }) // perform the prefetch when the throttled hovered post id changes useEffect(() => { if (throttledHoveredPostId) { queryClient.ensureQueryData({ queryKey: ['post', throttledHoveredPostId], queryFn: () => fetchPost(throttledHoveredPostId), }) } }, [throttledHoveredPostId]) const handleMouseEnter = (postId: number) => { setCurrentHoveredPostId(postId) // update the hovered post id } if (isLoading) return <div>Loading posts...</div> return ( <div> <h2>Posts</h2> <ul style={{ margin: 0, padding: 0 }}> {posts?.map((post: { id: number; title: string }) => ( <li key={post.id} style={{ margin: '2px 0' }}> <a href={`#post-${post.id}`} onMouseEnter={() => handleMouseEnter(post.id)} onClick={() => setSelectedPostId(post.id)} style={{ display: 'block', padding: '4px', cursor: 'pointer' }} > {post.title} </a> </li> ))} </ul> </div> ) } function PostDetail({ postId }: { postId: number }) { const { data: post, isLoading } = useQuery({ queryKey: ['post', postId], queryFn: () => fetchPost(postId), }) if (isLoading) return <div>Loading post...</div> return ( <div> <h3>{post?.title}</h3> <p>{post?.body}</p> </div> ) } function App() { const [selectedPostId, setSelectedPostId] = React.useState<number | null>( null, ) return ( <div className="App" style={{ maxWidth: '800px', margin: '0 auto', padding: '20px' }} > <h1>TanStack Pacer/Query Throttled Prefetch Example</h1> <p>Hover over a post title to prefetch its content</p> <p> This example shows how to prefetch a query when the user hovers over a post. </p> <p> The throttled query key is created after a throttle to avoid excessive prefetches. </p> <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }} > <PostList setSelectedPostId={setSelectedPostId} /> {selectedPostId && <PostDetail postId={selectedPostId} />} </div> </div> ) } const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 10_000, }, }, }) const root = ReactDOM.createRoot(document.getElementById('root')!) root.render( <QueryClientProvider client={queryClient}> <App /> <ReactQueryDevtools initialIsOpen={false} /> </QueryClientProvider>, ) 
Subscribe to Bytes

Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.

Subscribe to Bytes

Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.