Capítulo 25 de 80

Chapter 25: Placeholder Query Data

Core Idea

placeholderData makes a query render as if it already has data (starting in success state, not pending) without persisting anything to the cache — the mechanism for showing partial/preview/fake data while the real fetch happens in the background.

Key Concepts

  • Not persisted, unlike initialData: this is the core distinction from Chapter 24 — placeholder data is display-only, never written into the actual cache entry.
  • State shape: a query using placeholderData starts in status: 'success'/isSuccess: true with isPlaceholderData: true, letting you distinguish "this is fill-in data" from "this is the real fetched result" without a separate loading branch.
  • Static value: pass a value directly (e.g. a small "preview" object) as placeholderData.
  • Memoized value: wrap expensive-to-compute placeholder generation in useMemo so it isn't recomputed every render.
  • Function form: placeholderData: (previousData, previousQuery) => ... gives access to the previous successful query's data/meta — this is exactly the mechanism keepPreviousData (Chapter 22) is built from, for carrying old data across a changing key.
  • Sourced from another query's cache: e.g. pull a lightweight "preview" version of a blog post from an already-cached list query as placeholder data for the individual post query, so detail views render instantly from list data already in memory while the full record loads.

Code Examples

// Static placeholder value
useQuery({ queryKey: ['todos'], queryFn: () => fetch('/todos'), placeholderData: placeholderTodos })

// Sourced from a sibling query's cache — instant "preview" render
function BlogPost({ blogPostId }) {
  const queryClient = useQueryClient()
  return useQuery({
    queryKey: ['blogPost', blogPostId],
    queryFn: () => fetch(`/blogPosts/${blogPostId}`),
    placeholderData: () =>
      queryClient.getQueryData(['blogPosts'])?.find((d) => d.id === blogPostId),
  })
}
  • What it demonstrates: a static placeholder value, and deriving a placeholder from a sibling query's already-cached list data for an instant detail-view render.

Key Takeaways

  1. Use placeholderData (never initialData) for genuinely partial/fake/preview data — persisting incomplete data via initialData risks that shape leaking into real cache reads elsewhere.
  2. Check isPlaceholderData whenever the UI needs to tell placeholder content apart from the real fetched result (e.g. before enabling an action that depends on complete data).
  3. Deriving placeholder data from a sibling query's cache (list → detail) is a common, cheap way to make detail views feel instant.

Connects To

  • Initial Query Data: the persisted counterpart to this chapter's non-persisted placeholder data.
  • Paginated / Lagged Queries: keepPreviousData, built on the function form of placeholderData shown here.