Skip to main content
Docs

Read session and user data in your React Router app with Clerk

Clerk provides a set of hooks and helpers that you can use to access the active session and user data in your React Router application. Here are examples of how to use these helpers in both the client and server-side to get you started.

Server-side

To access active session and user data on the server-side, use the getAuth() helper.

Server data loading

The getAuth() helper returns the Auth object of the currently active user, which contains important information like the current user's session ID, user ID, and organization ID. The userId can be used to protect your API routes.

In some cases, you may need the full Backend User object of the currently active user. This is helpful if you want to render information, like their first and last name, directly from the server. The clerkClient() helper returns an instance of the JavaScript Backend SDK, which exposes Clerk's Backend API resources through methods such as the getUser() method. This method returns the full Backend User object.

In the following example, the userId is passed to the Backend SDK's getUser() method to get the user's full Backend User object.

app/routes/profile.tsx
import { redirect } from 'react-router'
import { getAuth } from '@clerk/react-router/ssr.server'
import { createClerkClient } from '@clerk/react-router/api.server'
import type { Route } from './+types/profile'

export async function loader(args: Route.LoaderArgs) {
  // Use `getAuth()` to get the user's ID
  const { userId } = await getAuth(args)

  // Protect the route by checking if the user is signed in
  if (!userId) {
    return redirect('/sign-in?redirect_url=' + args.request.url)
  }

  // Instantiate the Backend SDK and get the user's full `Backend User` object
  const user = await createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY }).users.getUser(
    userId,
  )

  return {
    user: JSON.stringify(user),
  }
}

export default function Profile({ loaderData }: Route.ComponentProps) {
  return (
    <div>
      <h1>Profile Data</h1>
      <pre>
        <code>{JSON.stringify(loaderData, null, 2)}</code>
      </pre>
    </div>
  )
}

Server action

Unlike the previous example that loads data when the page loads, the following example uses getAuth() to only fetch user data after submitting the form. The helper runs on form submission, authenticates the user, and processes the form data.

app/routes/profile-form.tsx
import { redirect, Form } from 'react-router'
import { getAuth } from '@clerk/react-router/ssr.server'
import { createClerkClient } from '@clerk/react-router/api.server'
import type { Route } from './+types/profile-form'

export async function action(args: Route.ActionArgs) {
  // Use `getAuth()` to get the user's ID
  const { userId } = await getAuth(args)

  // Protect the route by checking if the user is signed in
  if (!userId) {
    return redirect('/sign-in?redirect_url=' + args.request.url)
  }

  // Get the form data
  const formData = await args.request.formData()
  const name = formData.get('name')?.toString()

  // Instantiate the Backend SDK and get the user's full `Backend User` object
  const user = await createClerkClient({
    secretKey: process.env.CLERK_SECRET_KEY,
  }).users.getUser(userId)

  return {
    name,
    user: JSON.stringify(user),
  }
}

export default function ProfileForm({ actionData }: Route.ComponentProps) {
  return (
    <div>
      <h1>Profile Data</h1>

      <Form method="post">
        <label htmlFor="name">Name</label>
        <input type="text" name="name" id="name" />
        <button type="submit">Submit</button>
      </Form>

      {actionData ? (
        <pre>
          <code>{JSON.stringify(actionData, null, 2)}</code>
        </pre>
      ) : null}
    </div>
  )
}

Client-side

To access active session and user data on the client-side, use the useAuth() and useUser() hooks.

useAuth()

The following example uses the useAuth() hook to access the current auth state, as well as helper methods to manage the current active session. The hook returns userId, which can be used to protect your routes.

example.tsx
export default function Example() {
  const { isLoaded, isSignedIn, userId, sessionId, getToken } = useAuth()

  if (!isLoaded) {
    return <div>Loading...</div>
  }

  if (!isSignedIn) {
    // You could also add a redirect to the sign-in page here
    return <div>Sign in to view this page</div>
  }

  return (
    <div>
      Hello, {userId}! Your current active session is {sessionId}.
    </div>
  )
}

The following example uses the useUser() hook to access the User object, which contains the current user's data such as their full name. The isLoaded and isSignedIn properties are used to handle the loading state and to check if the user is signed in, respectively.

src/Example.tsx
export default function Example() {
  const { isSignedIn, user, isLoaded } = useUser()

  if (!isLoaded) {
    return <div>Loading...</div>
  }

  if (!isSignedIn) {
    return <div>Sign in to view this page</div>
  }

  return <div>Hello {user.firstName}!</div>
}

Feedback

What did you think of this content?

Last updated on