clerk-react-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseReact SPA Patterns
React SPA 模式
This skill coversfor Vite/CRA SPAs. For Next.js use@clerk/react. For TanStack Start useclerk-nextjs-patterns.clerk-tanstack-patterns
本技能介绍适用于Vite/CRA单页应用的使用方法。Next.js场景请使用@clerk/react,TanStack Start场景请使用clerk-nextjs-patterns。clerk-tanstack-patterns
What Do You Need?
所需内容
| Task | Reference |
|---|---|
| useAuth / useUser / useClerk hooks | references/hooks.md |
| Protected routes with React Router | references/protected-routes.md |
| Custom sign-in / sign-up forms | references/custom-flows.md |
| React Router v6/v7 integration | references/router-integration.md |
| 任务 | 参考文档 |
|---|---|
| useAuth / useUser / useClerk 钩子 | references/hooks.md |
| 基于React Router的受保护路由 | references/protected-routes.md |
| 自定义登录/注册表单 | references/custom-flows.md |
| React Router v6/v7 集成 | references/router-integration.md |
References
参考文档
| Reference | Description |
|---|---|
| useAuth, isLoaded guard |
| ProtectedRoute pattern |
| useSignIn, useSignUp flows |
| React Router v6/v7 setup |
| 文档路径 | 描述 |
|---|---|
| useAuth、isLoaded守卫 |
| ProtectedRoute 模式 |
| useSignIn、useSignUp 流程 |
| React Router v6/v7 配置 |
Setup
安装配置
npm install @clerk/react.envVITE_CLERK_PUBLISHABLE_KEY=pk_...src/main.tsxtsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { ClerkProvider } from '@clerk/react'
import App from './App.tsx'
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
createRoot(document.getElementById('root')!).render(
<StrictMode>
<ClerkProvider publishableKey={PUBLISHABLE_KEY}>
<App />
</ClerkProvider>
</StrictMode>,
)npm install @clerk/react.envVITE_CLERK_PUBLISHABLE_KEY=pk_...src/main.tsxtsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { ClerkProvider } from '@clerk/react'
import App from './App.tsx'
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
createRoot(document.getElementById('root')!).render(
<StrictMode>
<ClerkProvider publishableKey={PUBLISHABLE_KEY}>
<App />
</ClerkProvider>
</StrictMode>,
)Mental Model
心智模型
@clerk/reactauth()- must be
isLoadedbefore trustingtrue— always guard onisSignedInisLoaded - gives access to
useClerk(),signOut,openSignInand other methodsopenUserProfile - from
getToken()fetches the session JWT for API callsuseAuth()
@clerk/reactauth()- 在信任取值前必须确保
isSignedIn为isLoaded——始终要先做true校验isLoaded - 可访问
useClerk()、signOut、openSignIn等方法openUserProfile - 提供的
useAuth()可获取会话JWT用于API调用getToken()
Minimal Pattern
最简示例
tsx
import { useAuth } from '@clerk/react'
export function Dashboard() {
const { isLoaded, isSignedIn, userId } = useAuth()
if (!isLoaded) return <div>Loading...</div>
if (!isSignedIn) return <div>Please sign in</div>
return <div>Hello {userId}</div>
}tsx
import { useAuth } from '@clerk/react'
export function Dashboard() {
const { isLoaded, isSignedIn, userId } = useAuth()
if (!isLoaded) return <div>Loading...</div>
if (!isSignedIn) return <div>Please sign in</div>
return <div>Hello {userId}</div>
}Protected Route (React Router v6/v7)
受保护路由(React Router v6/v7)
tsx
import { Navigate, Outlet } from 'react-router-dom'
import { useAuth } from '@clerk/react'
export function ProtectedRoute() {
const { isLoaded, isSignedIn } = useAuth()
if (!isLoaded) return <div>Loading...</div>
if (!isSignedIn) return <Navigate to="/sign-in" replace />
return <Outlet />
}tsx
<Routes>
<Route element={<ProtectedRoute />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Route>
<Route path="/sign-in" element={<SignIn />} />
</Routes>tsx
import { Navigate, Outlet } from 'react-router-dom'
import { useAuth } from '@clerk/react'
export function ProtectedRoute() {
const { isLoaded, isSignedIn } = useAuth()
if (!isLoaded) return <div>Loading...</div>
if (!isSignedIn) return <Navigate to="/sign-in" replace />
return <Outlet />
}tsx
<Routes>
<Route element={<ProtectedRoute />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Route>
<Route path="/sign-in" element={<SignIn />} />
</Routes>Token for API Calls
API调用令牌获取
tsx
import { useAuth } from '@clerk/react'
export function DataFetcher() {
const { getToken } = useAuth()
async function fetchData() {
const token = await getToken()
if (!token) return
const res = await fetch('/api/data', {
headers: { Authorization: `Bearer ${token}` },
})
return res.json()
}
return <button onClick={fetchData}>Load</button>
}tsx
import { useAuth } from '@clerk/react'
export function DataFetcher() {
const { getToken } = useAuth()
async function fetchData() {
const token = await getToken()
if (!token) return
const res = await fetch('/api/data', {
headers: { Authorization: `Bearer ${token}` },
})
return res.json()
}
return <button onClick={fetchData}>Load</button>
}Common Pitfalls
常见陷阱
| Symptom | Cause | Fix |
|---|---|---|
| | Always check |
| Provider not at root | Wrap |
| Env var undefined | Wrong Vite prefix | Use |
Token is | User not signed in | Null-check |
| Sign-in component shows blank | No | Pass |
| 现象 | 原因 | 解决方案 |
|---|---|---|
| | 始终优先校验 |
提示 | 根组件未包裹Provider | 在 |
| 环境变量未定义 | Vite环境变量前缀错误 | 使用 |
Token返回 | 用户未登录 | 对 |
| 登录组件显示空白 | Provider未传入 | 显式传入 |
See Also
相关内容
- - Initial Clerk install
clerk-setup - - Custom flows & appearance
clerk-custom-ui - - B2B organizations
clerk-orgs
- - Clerk初始安装
clerk-setup - - 自定义流程与外观
clerk-custom-ui - - B2B组织管理
clerk-orgs