polling: refetchInterval: The query function is invoked every 5 seconds. RefetchInterval is best suited for scenarios where you have data that changes often and you always want the cache to be as up-to-date as possible.

refetchInterval:(query)=>{
	if(query.state.data?.finished){
		return false
	}
	return 3000
}

Prefetching: It's entirely likely that, even with prefetching, the user will still see a loading indicator if the response is slow.

<a href="#"
	onMouseEnter = { ()=>{
	queryClient.prrfetchQuery({
	queryKey: ["book"],
	queryFn: () => fetchBook(bookId)
	staleTime:6000
	})
}}> post </a>

Note: if you do not add staleTime, then it will fetch data every time when you hover the link, so add some staleTime, it can be some seconds or infinity.

initialData:()=>{
	return queryClient.getQueryData(['posts'])?.find(post=> post.path === path)
}

const {data, isPlaceholderData}= useQuery({
	queryKey: ["book"],
	queryFn: () => fetchBook(bookId),
	placeholderData:()=>{
		return queryClient.getQueryData(['posts'])?.find(post=> post.path === path)
	}
})

isPlaceholderData? <div>loading</div> : <div> actual data </div>

Note: First display the post title with a loader.