apollographql / apollo-client-nextjs

Apollo Client support for the Next.js App Router
https://www.npmjs.com/package/@apollo/experimental-nextjs-app-support
MIT License
448 stars 35 forks source link

SSR/RSC Rendering Behaviour #365

Open dml0031 opened 1 month ago

dml0031 commented 1 month ago

So I have been unable to work around an issue I am having using a server side query along with some suspense queries and how they are being rendered. This is how things are currently setup:

layout.tsx

export const dynamic = 'force-dynamic'

export default async function OrderOnlineLayout({ children }: React.PropsWithChildren) {
  const { data } = await query<BusinessOpenQuery, BusinessOpenQueryVariables>({
    query: BusinessOpenDocument,
    variables: {
      ids: [env.NEXT_PUBLIC_BUSINESS_ID],
      open: true
    },
    fetchPolicy: 'network-only',
    notifyOnNetworkStatusChange: true,
    context: {
      noCache: true
    }
  })

  if (data && data.businesses.length <= 0) return <OrderOnlineUnavailable operatingWeek={data.businessHours[0]?.operatingWeek} />

  return children
}

page.tsx

export default async function OrderOnlinePage({ searchParams }: PageProps) {
  const product = parseAsString.parseServerSide(searchParams.pid)
  const type = parseAsStringEnum(Object.values(OrderType)).parseServerSide(searchParams.type)

  return (
    <Suspense fallback={<LoadingIndicator className="min-h-screen" />}>
      <OrderOnline
        business_id={env.NEXT_PUBLIC_BUSINESS_ID}
        product_id={product}
        defaultOrderType={type}
        enable_analytics={env.NEXT_PUBLIC_ENVIRONMENT === 'production'}
        classNames={{ tabs: { wrapper: 'bg-primary', trigger: 'text-white data-[state=active]:bg-secondary data-[state=active]:text-primary' } }}
      />
    </Suspense>
  )
}

The issue that is happening is that when either directly going to the page, or navigating to the page from another for the first time, the conditional OrderOnlineUnavailable component is being rendered, followed by the suspense fallback, followed by the OrderOnlineUnavailable component again with the correct content.

I want / it should render directly into the LoadingIndicator by either the loading.tsx file however the awaited query doesnt seem to be being awaited at all.

In addition to that, if I load this page initially, then navigate to another page and come back, the query does not get run again even though the cache is set to cache: 'no-store' and the query fetchPolicy is set to network-only. I am only able to get the function to run again when reloading the page entirely.

Not sure if you have any insights here as far as either of these issues.

phryneas commented 1 month ago

Weird await behaviour in async components sounds to me like it would either be a bug in React, or you're maybe accidentally rendering an async component in a Client Tree and not a browser tree? I'm sorry I have no better suggestions here :/

In addition to that, if I load this page initially, then navigate to another page and come back, the query does not get run again even though the cache is set to cache: 'no-store' and the query fetchPolicy is set to network-only. I am only able to get the function to run again when reloading the page entirely.

This sounds to me like the Next.js router cache which caches server components for 60 seconds or so client-side without ever rerunning them.