Upgrading from v2 to v3
On March 24, 2022, Clerk launched version 3 of its full suite of JavaScript libraries, including our SDKs for React, Next.js, Gatsby, Remix, and Redwood. This guide helps you with uprading to the next major version of your SDK.
Why upgrade?
Version 3 includes a number of bug fixes, developer experience improvements, and altogether new features, including:
- Support for server-side rendering
- Reduced React re-renders
- Improved Typescript types and IntelliSense autocomplete
Client-side changes (all frameworks)
These changes apply to all frameworks, regardless of which one you use specifically.
Upgrade dependencies
terminalnpm install @clerk/nextjs@latest
terminalnpm install @clerk/clerk-react@latest
useAuth()
introduction
useAuth()
is a new, SSR-compatible hook that is recommended for all authentication tasks.
const { userId, sessionId, getToken, isLoaded, isSignedIn, signOut } = useAuth();
The useAuth()
hook unifies the way you access common auth operations. It replaces:
useSession()
to accessgetToken()
or thesessionId
useUser()
to accessgetToken()
for integrationsuseClerk()
to accesssignOut()
<SignedIn>
and<SignedOut>
in a way that requires extra components
Hook and component API changes
Version 3 changes several APIs for improved consistency and usability.
useUser()
and useSession()
Previously, useUser
and useSession
could only be called from inside the <SignedIn>
component. This restriction has been relaxed, but now developers must manually handle the possibility the user and session objects may not be loaded when the hook is called.
In a future version, we plan to support React <Suspense />
to make this even easier.
Old API | New API |
---|---|
const user = useUser(); | const { isLoaded, isSignedIn, user } = useUser(); |
const session = useSession(); | const { isLoaded, isSignedIn, session } = useSession(); If you only call useSession for the ID or getToken , please switch to useAuth() instead. |
<RedirectToSignIn />
and <RedirectToSignUp/>
The behavior enabled by the returnBack
prop has now been promoted to default behavior. returnBack
is deprecated in favor of using an empty component.
Old API | New API |
---|---|
<RedirectToSignIn returnBack/> | <RedirectToSignIn /> |
<RedirectToSignUp returnBack/> | <RedirectToSignUp /> |
<SignIn />
and <SignUp />
Props which take URLs (absolute or relative) have been standardized to use the Url (camelCase) suffix.
Old API | New API |
---|---|
afterSignIn | afterSignInUrl |
afterSignUp | afterSignUpUrl |
signUpURL | signUpUrl |
signInURL | signInUrl |
<UserButton />
Props which take URLs (absolute or relative) have been standardized to use the Url (camelCase) suffix.
Old API | New API |
---|---|
afterSwitchSession | afterSwitchSessionUrl |
userProfileURL | userProfileUrl |
signInURL | signInUrl |
afterSignOutAll | afterSignOutUrl |
afterSignOutOne | afterMultiSessionSingleSignOutUrl |
useSignUp()
& useSignIn()
useSignUp()
and useSignIn()
are no longer required to be contained in <SignedOut>
or <ClerkLoaded>
. Instead, they have been updated to include a loading state.
Old API | New API |
---|---|
const signUp = useSignUp(); | const { isLoaded, signUp } = useSignUp(); |
const signIn = useSignIn(); | const { isLoaded, signIn } = useSignIn(); |
Resource changes
In order to make our APIs easier to use in codebases not using Typescript and make them more consistent across frameworks, we removed support for snake_cased method parameters. We also updated all method signatures to always accept a param object instead of plain positional params.
We expect that most users will only need to apply these changes to the user.update()
, user.createEmailAddress()
and user.createPhoneNumber()
methods as shown below.
Users who have built custom auth flows using the SignIn and SignUp resources can consult the SignUp and SignIn section below.
User
User.getToken("token-name")
has been deprecated and is now accessible through getToken
from the useAuth()
hook or Session.getToken()
.
The new getToken()
method accepts an optional { template: string; }
object, used to specify the JWT template you want to use.
Please note that If you want to fetch a token for an integration, you must prefix the integration name with integration_
, eg: getToken({ template: 'integration_firebase' })
.
Moreover, the following methods now accept a params objects instead of positional params: createEmailAddress()
, createPhoneNumber()
, setProfileImage()
.
Respecting the camelCase changes we explained at the start of this section, all method params should now use camelCasing. An example for the create method is shown below.
Old API | New API |
---|---|
User.getToken("token-name") | const { getToken } = useAuth(); or getToken({ template: "integration_token-name" }) or Session.getToken({template: "integration_token-name"}) |
User.createEmailAddress(value) | User.createEmailAddress({ email: value }) |
User.createPhoneNumber(value) | User.createPhoneNumber({ phoneNumber: value }) |
User.setProfileImage(file) | User.setProfileImage(file) |
User.update({ first_name: "", last_name: "" }) | User.update({ firstName: "", lastName: "" }) |
SignUp and SignIn
The createEmailLinkFlow
and authenticateWithRedirect
calls have had parameters renamed to use the word "redirect" instead of "callback."
Old API | New API |
---|---|
createEmailLinkFlow({ callbackUrl }) | createEmailLinkFlow({ redirectUrl }) |
authenticateWithRedirect({ callbackUrl, callbackUrlComplete }) | authenticateWithRedirect({ redirectUrl, redirectUrlComplete }) |
Next.js server-side changes
Before starting this guide, please complete the Client-side changes.
API routes
Helpers for API routes have been updated to mirror the new useAuth()
hook on the client-side.
withSession
is deprecated and replaced withwithAuth
requireSession
is deprecated with replaced withrequireAuth
- Instead of decorating the
Request
object with aSession
object, it is now decorated with anAuth
object that mirrorsuseAuth()
on the client-side.const { userId, sessionId, getToken } = req.auth;
Example usage
import { withAuth } from "@clerk/nextjs/api"; export default withAuth(async (req, res) => { const { userId, sessionId, getToken } = req.auth; const hasuraToken = await getToken({template: "hasura"}); // Your handler });
Edge middleware
Edge middleware has also been updated to mirror the new useAuth()
hook on the client-side. The import path has also been changed to avoid confusion.
import { withEdgeMiddlewareAuth } from "@clerk/nextjs/edge-middleware"; export const middleware = withEdgeMiddlewareAuth((req, ev) => { const { userId, sessionId, getToken } = req.auth; // Your middleware });
Express server-side changes
Before starting this guide, please complete the Client-side changes.
Middleware
Express middleware been updated to mirror the new useAuth()
hook on the client-side.
ClerkExpressWithSession
is deprecated and replaced withClerkExpressWithAuth
ClerkExpressRequireSession
is deprecated and replaced withClerkExpressRequireAuth
- Instead of decorating the
Request
object with aSession
object, it is now decorated with anAuth
object that mirrorsuseAuth()
on the client-side.const { userId, sessionId, getToken } = req.auth;
Example usage
import { ClerkExpressRequireAuth } from '@clerk/clerk-sdk-node'; app.use(ClerkExpressRequireAuth()); app.get('/', (req, res) => { const { userId, sessionId, getToken } = req.auth; // Your handler... })