Next.js rendering modes and Clerk
By default, Next.js attempts to optimize your application by statically generating pages at build-time that do not depend on data from the request. However, authentication data is inherently dynamic and depends on the request, meaning that it is not available at build-time.
To facilitate Next.js's default behavior, Clerk provides an opt-in approach to accessing authentication data so that you can opt-in specific routes to dynamic rendering, while still using statically rendered pages for others.
The following options are available for accessing authentication data:
- The
auth()
helper can only be used in Server Components, but the data can be passed to Client Components if desired. It opts your entire route into dynamic rendering. - The
useAuth()
hook can only be used in Client Components. Due to Next.js's default behavior, these components will be statically rendered. However, you can wrap them with<ClerkProvider dynamic>
to opt them into dynamic rendering.
Access auth data with auth()
The auth()
helper returns the user's authentication state in Server Components. The data can be passed to Client Components if desired. This is a dynamic API that relies on request-time data so using auth()
will opt your entire route into dynamic rendering.
import { auth } from '@clerk/nextjs/server'
// This page will be dynamically rendered at request time
export default async function Page() {
const { userId } = await auth()
// This will be immediately available on first render
console.log(userId)
return <p>Hello, {userId}</p>
}
Access auth data with useAuth()
useAuth()
provides authentication data in Client Components. Due to Next.js's default behavior, these components will be statically rendered. If that's fine with you, see the reference docs for more information, like code examples.
However, if you'd like the components that use useAuth()
to be dynamically rendered, you can wrap them with <ClerkProvider dynamic>
. If you're using PPR, consider wrapping <ClerkProvider dynamic>
in <Suspense>
so that the boundary fallback is included in the prerendered HTML.
import { ClerkProvider } from '@clerk/nextjs'
import { Suspense } from 'react'
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<Suspense fallback={<Skeleton />}>
<ClerkProvider dynamic>{children}</ClerkProvider>
</Suspense>
)
}
function Skeleton() {
return <div>Loading...</div>
}
'use client'
import { useAuth } from '@clerk/nextjs'
export default function Page() {
const { userId, sessionId, isSignedIn } = useAuth()
// All of these will be immediately available on first render
console.log(userId, sessionId, isSignedIn)
return (
<div>
<h1>Test Page</h1>
<p>User ID: {userId}</p>
</div>
)
}
Feedback
Last updated on