trpc icon indicating copy to clipboard operation
trpc copied to clipboard

Suspense fallback shows empty screen before data when using prefetch in Server Components

Open dgd03146 opened this issue 1 year ago โ€ข 0 comments

Provide environment information

System:
  OS: Windows 11
  CPU: (8) x64
  Memory: 16 GB
  Shell: PowerShell
Binaries:
  Node: 20.11.1
  pnpm: 8.15.4
Browsers:
  Chrome: 122.0.6261.112
npmPackages:
  typescript: 5.4.5
  next: 14.2.3
  react: 18.3.1
  react-dom: 18.3.1
  @trpc/server: 11.0.0-rc.467
  @trpc/client: 11.0.0-rc.467
  @trpc/react-query: 11.0.0-rc.467
  @trpc/next: 11.0.0-rc.467
  @tanstack/react-query: 5.40.0
  @tanstack/react-query-devtools: 5.40.0

Describe the bug

When using prefetch in a Server Component with Suspense, the component shows the Suspense fallback first, then briefly shows an empty screen before finally displaying the data. This creates a jarring user experience with multiple visual states.

Following the [official documentation for Leveraging Suspense](https://trpc.io/docs/client/react/server-components#leveraging-suspense), but experiencing undesired loading states.

suspense error.webm

when I refresh the page it shows suspense fallback (skeleton) => empty screen => data

Link to reproduction

none

To reproduce

Server Component (app/gallery/photos/[id]/page.tsx):

export default function PhotoPage({ params }: { params: { id: string } }) {
  const photoId = params.id;

  void trpc.photos.getPhotoById.prefetch(photoId);

  return (
    <HydrateClient>
      <Suspense fallback={<PhotoDetailSkeleton />}>
        <PhotoDetail id={params.id} isModal={false} />
      </Suspense>
    </HydrateClient>
  );
}

Client Component Hook:

export function useGetPhotoById(id: string) {
  return trpc.photos.getPhotoById.useSuspenseQuery(id, {
    staleTime: 1000 * 60 * 5,
    gcTime: 1000 * 60 * 30,
    refetchOnMount: false,
    refetchOnWindowFocus: false,
  });
}

Additional information

Expected Behavior

The component should transition smoothly from Suspense fallback directly to the data without showing an empty screen in between.

Actual Behavior

The loading sequence is:

  1. Suspense fallback (skeleton)
  2. Empty screen
  3. Actual data

Additional Information

  • Using Next.js App Router
  • Following RSC patterns from tRPC documentation
  • Issue occurs consistently on initial load
  • Using latest tRPC RC version (11.0.0-rc.467)
  • Using latest React Query version (5.40.0)

Would appreciate guidance on how to achieve a smooth transition from skeleton to data without the empty screen flash.

๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Contributing

  • [X] ๐Ÿ™‹โ€โ™‚๏ธ Yes, I'd be down to file a PR fixing this bug!

dgd03146 avatar Nov 25 '24 03:11 dgd03146