Expo Native Components (beta)
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
Requirements
Native components require:
-
Expo SDK 53 or later. See the quickstart guide.
-
A development build (
npx expo run:iosornpx expo run:android), as these components are not available in Expo Go. -
The
@clerk/expoplugin configured in yourapp.jsonfile. See the available plugin options.app.json { "expo": { "plugins": ["@clerk/expo"] } } -
If using social connections, you must register your native application credentials in the Clerk Dashboard. See the Sign in with Google and Sign in with Apple guides for setup steps.
Expo plugin options
The plugin accepts the following options:
- Name
appleSignIn- Type
boolean- Description
Whether to add the
com.apple.developer.applesigninentitlement. Set tofalseif your app does not use Apple Sign In. Defaults totrue.
- 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 Theming reference for platform-specific details and the full schema.
{
"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:
- Native Authentication - User authenticates through the native UI
- Session Created - Native SDK creates and manages the session
- Session Sync -
@clerk/exposyncs the native session to the JS SDK - 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.
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:
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:
import { SignIn } from '@clerk/expo/web'
export default function SignInScreen() {
return <SignIn />
}See the web component reference for more information.
Feedback
Last updated on