javascript icon indicating copy to clipboard operation
javascript copied to clipboard

In nextjs/app-beta, the UserButton doesn't seem to work with Suspense?

Open kleemeo opened this issue 2 years ago • 11 comments

Trying to use the UserButton component in a next 13 server component. I understand there's some time needed to fetch the data from the user via Clerk's api and retrieve the image.

I was wondering why this component/pattern doesn't adhere to the <Suspense /> loading pattern. (Loading UI doesn't show before the component/image is ready)

I've attached a gif of what it's kind of doing, and it does the same even when wrapped with:

  <Suspense fallback={<p>loading...</p>}>
      <UserButton />
  </Suspense>

delay

Am I doing something wrong here or is the implementation of UserButton just doesn't really allow the effects of Suspense as it loads? Sorry if I'm missing something here. Still new to app-router and the clerk app-beta.

Thanks!

kleemeo avatar May 03 '23 16:05 kleemeo

I am also seeing this behaviour, did you find a solution or does anyone else know if there is one?

lhennerley avatar May 17 '23 16:05 lhennerley

@lhennerley unfortunately not really, please let me know if you or anyone else have figured out the reason for this or a workaround?

I am sure it's something to do with an imported client component not being able to be captured by the Suspense boundaries. Or the fetching of the client component is not registered as a fetch

kleemeo avatar May 19 '23 14:05 kleemeo

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 10 days.

clerk-cookie avatar Jun 18 '23 18:06 clerk-cookie

This issue was closed because it has been stalled for 10 days with no activity.

clerk-cookie avatar Jun 28 '23 18:06 clerk-cookie

I am seeing this issue of reloading/ flickering, during navigation also (NextJs 13 AppRouter)

mkgo avatar Jul 05 '23 14:07 mkgo

I am seeing this issue of reloading/ flickering, during navigation also (NextJs 13 AppRouter)

yeah no way to make it work with suspense, but I just stop the layout shift by putting it in a div and setting the width and height

Apestein avatar Jul 21 '23 14:07 Apestein

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 10 days.

clerk-cookie avatar Aug 20 '23 18:08 clerk-cookie

Small update - we are working on a resolution for this one. So sorry for the delays!

jescalan avatar Aug 25 '23 16:08 jescalan

im having an issue with the userButton gives hydration error in next 13 and this userButton causing it

xNOVA2 avatar Oct 07 '23 17:10 xNOVA2

@xNOVA2 The best way to get this addressed would be to open a new issue and provide a minimal reproduction 🙏

jescalan avatar Nov 16 '23 15:11 jescalan

For me, it works well :

import Loading from "@/app/loading";
import { ClerkLoading, SignedIn, SignedOut, UserButton } from "@clerk/nextjs";

export default async function User() {
  return (
    <>
      <ClerkLoading>
        <Loading />
      </ClerkLoading>
      <SignedOut>
        <Link href="/education/sign-in" className={styles.linkSignin}>Entrar</Link>
      </SignedOut>
      <SignedIn>
        <UserButton afterSignOutUrl="/education" />
      </SignedIn>
    </>
  )
}

use ClerkLoading

yureribeiro avatar Jan 08 '24 20:01 yureribeiro

Using <ClerkLoading> there's still a tiny flash of layout shift right when the <ClerkLoading> disappears and the <UserButton> appears.

alexilyaev avatar Nov 06 '24 17:11 alexilyaev

We introduced a temporary solution with the fallback prop.

panteliselef avatar Jan 01 '25 15:01 panteliselef

fallback helps most of the time 👍

On slower devices (e.g. 4G network + 4x CPU throttle), we still see hydration errors "Text content does not match server-rendered HTML" because the server renders the fallback, but the client ends up rendering the full UserButton, so there is a mismatch. Workaround is to wrap UserButton in something like this:

function UserButtonFallback({ children }: PropsWithChildren) {
  return (
    <Box sx={{ position: 'relative', width: 28, height: 28 }}>
      <Skeleton variant="circular" width={28} height={28} sx={{ position: 'absolute' }} />
      <NoSsr>{children}</NoSsr>
    </Box>
  );
}

aldenquimby avatar May 15 '25 11:05 aldenquimby