clerk-expo-patterns 是做什么的?
Expo / React Native 模式与 Clerk — SecureStore 令牌缓存、OAuth 深度链接、原生 useAuth、Expo Router 受保护路由、带用户上下文的推送通知。触发关键词:expo clerk、clerk react native、SecureStore 令牌缓存、expo router 认证、OAuth 深度链接 clerk、移动认证 clerk。
概述
此技能提供了一套经过验证的模式,用于在 Expo / React Native 应用中集成 Clerk 身份认证。涵盖了从令牌安全存储到复杂 OAuth 流程的所有方面,确保你的移动应用认证体验既安全又流畅。
关键模式
1. SecureStore 令牌缓存
使用 Expo 的 SecureStore 安全存储 Clerk 的会话令牌,避免重复登录。
import * as SecureStore from 'expo-secure-store';
import { ClerkProvider } from '@clerk/clerk-expo';
const tokenCache = {
async getToken(key: string) {
try {
return SecureStore.getItemAsync(key);
} catch (err) {
return null;
}
},
async saveToken(key: string, value: string) {
try {
return SecureStore.setItemAsync(key, value);
} catch (err) {
return;
}
},
};
export default function App() {
return (
<ClerkProvider tokenCache={tokenCache} publishableKey={process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY}>
{/* 你的应用 */}
</ClerkProvider>
);
}
2. OAuth 深度链接
配置 OAuth 深度链接以支持在原生应用中使用社交登录(如 Google、Apple、GitHub)。
// app.json
{
"expo": {
"scheme": "yourapp",
"plugins": [
[
"expo-router",
{
"scheme": "yourapp"
}
]
]
}
}
// 在 ClerkProvider 中配置深度链接
import { ClerkProvider, OAuthStrategy } from '@clerk/clerk-expo';
<ClerkProvider
tokenCache={tokenCache}
publishableKey={process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY}
// 自动处理深度链接
>
3. 原生 useAuth
在原生组件中正确使用 useAuth Hook。
import { useAuth } from '@clerk/clerk-expo';
function ProtectedComponent() {
const { isSignedIn, userId, sessionId } = useAuth();
if (!isSignedIn) {
return null; // 或重定向到登录
}
return <Text>用户已登录: {userId}</Text>;
}
4. Expo Router 受保护路由
使用 Expo Router 和 Clerk 实现基于认证状态的路由保护。
// app/_layout.tsx
import { Redirect, Stack } from 'expo-router';
import { useAuth } from '@clerk/clerk-expo';
export default function AppLayout() {
const { isSignedIn } = useAuth();
if (!isSignedIn) {
return <Redirect href="/sign-in" />;
}
return <Stack />;
}
5. 带用户上下文的推送通知
将推送通知与当前用户关联。
import { useAuth } from '@clerk/clerk-expo';
import * as Notifications from 'expo-notifications';
function usePushNotifications() {
const { userId, getToken } = useAuth();
useEffect(() => {
if (!userId) return;
async function registerForPushNotifications() {
const { status } = await Notifications.requestPermissionsAsync();
if (status !== 'granted') return;
const token = await Notifications.getExpoPushTokenAsync();
// 将 token 发送到后端,关联 userId
await fetch('/api/register-push-token', {
method: 'POST',
headers: {
'Authorization': `Bearer ${await getToken()}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ userId, token: token.data }),
});
}
registerForPushNotifications();
}, [userId]);
}
触发说明
此技能在以下关键词出现时自动激活:
expo clerkclerk react nativeSecureStore token cacheexpo router authOAuth deep link clerkmobile auth clerk
平台支持
- ✅ Expo SDK 49+
- ✅ React Native 0.72+
- ✅ Clerk SDK v4+
- ✅ iOS & Android 原生
- ✅ Web(通过 Expo for Web)
最佳实践
- 始终使用 SecureStore:不要依赖 AsyncStorage 存储令牌,它不安全。
- 测试深度链接:确保你的 app scheme 已正确配置。
- 处理用户注销:清除 SecureStore 中的令牌。
- 错误处理:在
getToken和saveToken中添加 try-catch。 - 环境变量:使用
EXPO_PUBLIC_前缀暴露给客户端。
常见问题
Q: 为什么我的令牌没有持久化?
确保你的 tokenCache 实现没有错误,并且 SecureStore 在 iOS 模拟器和 Android 模拟器上都能正常工作。
Q: OAuth 深度链接在 iOS 上不起作用?
检查你的 Info.plist 是否包含正确的 URL scheme 配置。
Q: 如何在应用启动时检查认证状态?
Clerk 会自动从 SecureStore 恢复会话,无需手动检查。