Skip to main content
Docs

Expo Native Components (beta)

Warning

Expo native components are currently in beta. If you run into any issues, please reach out to our support team.

The Clerk Expo SDK provides prebuilt native UI components rendered with SwiftUI on iOS and Jetpack Compose on Android. These components provide a fully native authentication experience while automatically synchronizing with the JavaScript SDK.

Available components

ComponentDescription
<AuthView />Expo IconFull sign-in and sign-up authentication UI
<UserButton />Expo IconCircular avatar button that opens the user profile
<UserProfileView />Expo IconComplete profile management interface

Requirements

Native components require:

Expo plugin options

The plugin accepts the following options:

  • Name
    appleSignIn
    Type
    boolean
    Description

    Whether to add the com.apple.developer.applesignin entitlement. Set to false if your app does not use Apple Sign In. Defaults to true.

  • Name
    keychainService
    Type
    string
    Description

    Custom keychain service identifier. Required if you need extension targets (widgets, App Clips, Watch) to share the keychain with the main app.

app.json
{
  "expo": {
    "plugins": [
      [
        "@clerk/expo",
        {
          "appleSignIn": false,
          "keychainService": "com.example.myapp"
        }
      ]
    ]
  }
}

How it works

The native components handle authentication through the native Clerk SDKs (clerk-ios and clerk-android). When authentication completes, the session is automatically synchronized to the JavaScript SDK:

  1. Native Authentication - User authenticates through the native UI
  2. Session Created - Native SDK creates and manages the session
  3. Session Sync - @clerk/expo syncs the native session to the JS SDK
  4. JS SDK Ready - All hooks (useUser, useAuth, useSession, etc.) reflect the authenticated state

Session synchronization

Native components do not use imperative callbacks. Instead, use hooks like useAuth(), useUser(), or useSession() in a useEffect to react to authentication state changes.

Important

When using native components, pass { treatPendingAsSignedOut: false } to useAuth() to keep auth state in sync with the native SDK and avoid issues with pending .

app/(auth)/sign-in.tsx
import { AuthView } from '@clerk/expo/native'
import { useAuth } from '@clerk/expo'
import { useRouter } from 'expo-router'
import { useEffect } from 'react'

export default function SignInScreen() {
  const { isSignedIn } = useAuth({ treatPendingAsSignedOut: false })
  const router = useRouter()

  useEffect(() => {
    if (isSignedIn) {
      router.replace('/(home)')
    }
  }, [isSignedIn])

  return <AuthView mode="signInOrUp" />
}

The same pattern applies to sign-out detection:

app/(home)/profile.tsx
import { UserProfileView } from '@clerk/expo/native'
import { useAuth } from '@clerk/expo'
import { useRouter } from 'expo-router'
import { useEffect } from 'react'

export default function ProfileScreen() {
  const { isSignedIn } = useAuth({ treatPendingAsSignedOut: false })
  const router = useRouter()

  useEffect(() => {
    if (!isSignedIn) {
      router.replace('/(auth)/sign-in')
    }
  }, [isSignedIn])

  return <UserProfileView style={{ flex: 1 }} />
}

Web compatibility

For Expo web projects, use the web-specific components from @clerk/expo/web:

app/sign-in.web.tsx
import { SignIn } from '@clerk/expo/web'

export default function SignInScreen() {
  return <SignIn />
}

See the web component reference for more information.

Feedback

What did you think of this content?

Last updated on