Skip to main content

Expo Native Components,

Beta

This feature is currently in beta. Functionality may change before general availability. 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 for Expo apps.

Important

These native components are for the iOS and Android surfaces. If you're building for Expo web, use Clerk's UI components instead.

<AuthView /> and <UserProfileView /> render inline in your React Native view hierarchy, so you can place them in a modal, route, full-screen view, or any other layout that fits your app. <UserButton /> renders the platform-native Clerk button and opens <UserProfileView /> when tapped.

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:

Installation

Native components require @clerk/expo-native-components, a separate package from @clerk/expo.

terminal
npx expo install @clerk/expo-native-components

Add the config plugin

Then add its config plugin to your app config, alongside @clerk/expo. See the available plugin optionsExpo Icon.

app.json
{
  "expo": {
    "plugins": ["@clerk/expo", "@clerk/expo-native-components"]
  }
}

Import the components

Rebuild your development build to include the native code. Then, import the components from @clerk/expo/native-components:

import { AuthView, UserButton, UserProfileView } from '@clerk/expo/native-components'
  • 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.

  • Name
    theme
    Type
    string
    Description

    Path to a JSON file that customizes the appearance of the native components on iOS and Android (colors, dark mode, border radius, and font family). See the ThemingExpo Icon reference for platform-specific details and the full schema.

  • 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
    faceIDPermission
    Type
    string
    Description

    The Face ID usage description that the plugin adds to your app's Info.plist as NSFaceIDUsageDescription. Required to support Face ID for biometric sign-in.

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

Respond to auth changes

Use hooks like useAuth(), useUser(), or useSession() to read authentication state and update your UI after auth changes.

Important

When using native components, pass { treatPendingAsSignedOut: false } to useAuth() so pending are not treated as signed out.

The following example demonstrates one way to open <AuthView />Expo Icon from a sign-in button.

Important

Keep the React Native <Modal> that contains <AuthView /> mounted at the same level as your signed-in and signed-out content. Don't render the modal only inside signed-out content, because auth state can change before required are finished and unmount the modal too early.

src/app/index.tsx
import { AuthView } from '@clerk/expo/native-components'
import { useAuth, useUser } from '@clerk/expo'
import { useState } from 'react'
import { Button, Modal, Text, View } from 'react-native'

export default function HomeScreen() {
  const { isSignedIn } = useAuth({ treatPendingAsSignedOut: false })
  const { user } = useUser()
  const [isAuthOpen, setIsAuthOpen] = useState(false)

  return (
    <View>
      {isSignedIn ? (
        <Text>User ID: {user?.id}</Text>
      ) : (
        <Button title="Sign in" onPress={() => setIsAuthOpen(true)} />
      )}
      <Modal
        animationType="slide"
        visible={isAuthOpen}
        presentationStyle="pageSheet"
        onRequestClose={() => setIsAuthOpen(false)}
      >
        <AuthView onDismiss={() => setIsAuthOpen(false)} />
      </Modal>
    </View>
  )
}

When rendering <AuthView />Expo Icon or <UserProfileView />Expo Icon directly in a route or full-screen view, pass isDismissible={false} if users must complete the flow to continue.

<AuthView isDismissible={false} />
<UserProfileView isDismissible={false} style={{ flex: 1 }} />

Web compatibility

For Expo web projects, use the web-specific components from @clerk/expo/web. Expo Router requires a non-platform route alongside a platform-specific route, so this example includes both files:

src/
└── app/
    ├── sign-in.tsx
    └── sign-in.web.tsx
src/app/sign-in.tsx
import { AuthView } from '@clerk/expo/native-components'

export default function Page() {
  return <AuthView isDismissible={false} />
}
src/app/sign-in.web.tsx
import { SignIn } from '@clerk/expo/web'

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

<AuthView /> doesn't navigate on its own — see the full-screen exampleExpo Icon for redirecting once authentication completes. See the web component reference for more information.

Feedback

What did you think of this content?

Last updated on