Skip to content

useInfiniteQuery: how to reliably distinguish initial load from confirmed empty result? #2707

@uriva

Description

@uriva

When using useInfiniteQuery on a page that may legitimately have zero results, I'm finding it tricky to render an "empty state" without flashing it briefly during the initial load.

The natural pattern would be:

const { data, isLoading } = useInfiniteQuery({ items: { $: { limit: 20 } } });
const items = data?.items ?? [];

if (isLoading) return <Spinner />;
if (items.length === 0) return <EmptyState />;
return <List items={items} />;

In practice, on first mount I sometimes see the empty state flash for a moment before the real results appear. It looks like isLoading flips to false (or data becomes a defined object with an empty array) before the actual page of results has arrived from the server, so items.length === 0 is briefly true even though there are items on the server.

A few questions:

  1. Is there a recommended way to distinguish "we haven't received the first page yet" from "first page arrived and is genuinely empty"?
  2. Is there a field on the result (something like pageInfo, an endCursor, a hasLoaded flag, etc.) that's intended for this?
  3. What's the idiomatic pattern people use for empty states with useInfiniteQuery?

Currently I'm working around it by gating the empty state behind a setTimeout, but that feels like a hack. Would love to know if there's a cleaner approach, or if this is something the hook could expose more directly.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions