Layout Shifts on async Slices

Greeting out there Prismic+NextJS world.

I am not 100% convinced that this is a Prismic issue. It's probably a "ME" issue, but as this is the best community of helpers I know of, I figure I'll ask this here.

I am trying to develop a Gallery slice. I have made this slice an async. The async bit itself isn't causing an issue. However, if I attempt to access Prismic content using the client, even if I don't use the returned data, there is a layout shift that occurs. If I comment out this client call, the layout shift goes away. I'm sure someone will tell me how I am forgetting a key React/NextJS concept of how to handle this. So grateful for anyone who can help:

const Gallery = async ({
  slice,
  context,
}: GalleryProps): Promise<JSX.Element> => {
  const { page } = context as contextProps
  const client = createClient()
// the await below causes the whole component to load after the page and causes a layout shift
  const photos = await client.getByType('gallery_item', {
    page: 1,
    pageSize: 24,
    orderings: {
      field: 'document.first_publication_date',
      direction: 'desc',
    },
    filters: [
      prismic.filter.any('document.tags', [slice.primary.tag || 'Car']),
    ],
  })

  return (
    <Section
      data-slice-type={slice.slice_type}
      data-slice-variation={slice.variation}
      width="xl"
    >
      {prismic.isFilled.richText(slice.primary.heading) && (
        <div className="mx-auto my-4 max-w-screen-lg lg:my-8">
          <PrismicRichText
            field={slice.primary.heading}
            components={{
              heading2: ({ children }) => (
                <Heading as="h2" size="4xl" className="lg:text-center">
                  {children}
                </Heading>
              ),
            }}
          />
        </div>
      )}
      {prismic.isFilled.richText(slice.primary.description) && (
        <div className="mx-auto my-4 max-w-screen-xl lg:my-8">
          <PrismicRichText field={slice.primary.description} />
        </div>
      )}
      <GalleryGoesHere />
    </Section>
  )
}

I keep coming back to the idea that maybe somehow Suspense will be the way to solve this. However, I've tried wrapping various things with <Suspense fallback={<div>Loading...</div>)></Suspense> and I've had no luck.

As I suspected, this was not a Prismic issue. I do hope that if anyone else decides to ride the same struggle :bus: , this post may help them.

If I am using a slice that needs to call the prismic client, I create a new server component in the same directory as the slice index.tsx file. This async server component will be the one to call the client and fetch data from Prismic. I then wrap this component in a Suspense component that has the fallback prop set to an element that is 100vh height. This displays a loader until the server component has finished loading. The result is a removal of the layout shift problem I was experiencing.

If someone knows of a better (proper) way of handling this, please share.

//my slice (seen above) has replaced GalleryGoesHere with below

<Suspense
   fallback={
      <div className="grid min-h-[calc(100vh-140px)] place-content-center">
         <LoaderCircle
             className="animate-spin text-primary"
              height={120}
              width={120}
              />
        </div>
        }
      >
    <GalleryList page={page} type="paginated" />
</Suspense>
1 Like