Use initialData only for complete data
Pass initialData only when you have the complete, authoritative value for a query.
Use placeholderData for anything partial or temporary, such as a preview from a list or the previous page while the next one loads.
Implementation
- Use
placeholderDatafor previews and previous results; it is shown while the query fetches and is never written to the cache. - Use
placeholderData: keepPreviousDatato keep showing the previous page or filter results while the next ones load. - Check
isPlaceholderDatato mark or disable UI that shows placeholder content. - Use
initialDataonly for complete data, and passinitialDataUpdatedAtsostaleTimeis measured from when that data was actually fetched. - For server rendering, prefer prefetching and hydrating the cache over passing
initialDatathrough props.
Rationale
initialData is written to the cache as if a fetch returned it.
Other components reading the same key receive it, and if it looks fresh under staleTime, no fetch replaces it.
Partial data in initialData therefore spreads incomplete data through the app.
placeholderData exists only for the observer that uses it and disappears once real data arrives.
Examples
Application: A preview from a list
Incorrect (counterexample):
const { data } = useQuery({
queryKey: ['posts', postId],
queryFn: () => fetchPost(postId),
initialData: postSummaryFromList,
});
The summary lacks the post body, but it is cached as the full post for every component that reads ['posts', postId].
Correct:
const { data, isPlaceholderData } = useQuery({
queryKey: ['posts', postId],
queryFn: () => fetchPost(postId),
placeholderData: postSummaryFromList,
});
Application: Paginated results
Correct:
const { data, isPlaceholderData } = useQuery({
queryKey: ['products', { page }],
queryFn: () => fetchProducts(page),
placeholderData: keepPreviousData,
});
The previous page stays visible, marked by isPlaceholderData, until the next page arrives.
Validation
For each initialData, check that the value is complete for the query and that initialDataUpdatedAt is set when the data came from an earlier fetch.
initialData holding a complete, authoritative value is not a violation.