Update for v5: use placeholderData
You can pass a function to placeholderData that returns previousData to automatically retain the previous data until the new data is available:
const result = useQuery({
queryKey: ['todos', id],
queryFn: () => fetch(`/todos/${id}`),
placeholderData: (previousData, previousQuery) => previousData,
})
https://tanstack.com/query/latest/docs/framework/react/guides/placeholder-query-data#placeholder-data-as-a-function
There is also a keepPreviousData function that is exported from @tanstack/react-query that can be used:
import { keepPreviousData, useQuery } from '@tanstack/react-query'
import React from 'react'
function Todos() {
const [page, setPage] = React.useState(0)
const fetchProjects = (page = 0) =>
fetch('/api/projects?page=' + page).then((res) => res.json())
const { isPending, isError, error, data, isFetching, isPlaceholderData } =
useQuery({
queryKey: ['projects', page],
queryFn: () => fetchProjects(page),
placeholderData: keepPreviousData,
})
return (
<div>
{isPending ? (
<div>Loading...</div>
) : isError ? (
<div>Error: {error.message}</div>
) : (
<div>
{data.projects.map((project) => (
<p key={project.id}>{project.name}</p>
))}
</div>
)}
<span>Current Page: {page + 1}</span>
<button
onClick={() => setPage((old) => Math.max(old - 1, 0))}
disabled={page === 0}
>
Previous Page
</button>
<button
onClick={() => {
if (!isPlaceholderData && data.hasMore) {
setPage((old) => old + 1)
}
}}
// Disable the Next Page button until we know a next page is available
disabled={isPlaceholderData || !data?.hasMore}
>
Next Page
</button>
{isFetching ? <span> Loading...</span> : null}
</div>
)
}
https://tanstack.com/query/latest/docs/framework/react/guides/paginated-queries#better-paginated-queries-with-placeholderdata