/** * React App Component with Clerk Hooks * * Demonstrates: * - useUser() for user data * - useAuth() for session tokens * - useClerk() for auth methods * - Proper loading state handling */ import { useUser, useAuth, useClerk, SignInButton, UserButton } from '@clerk/clerk-react' function App() { // Get user object (includes email, metadata, etc.) const { isLoaded, isSignedIn, user } = useUser() // Get auth state and session methods const { userId, getToken } = useAuth() // Get Clerk instance for advanced operations const { openSignIn, signOut } = useClerk() /** * CRITICAL: Always check isLoaded before rendering * * Why: Prevents flash of wrong content while Clerk initializes * Source: https://clerk.com/docs/references/react/use-user */ if (!isLoaded) { return (
Loading...
) } /** * Unauthenticated View */ if (!isSignedIn) { return (

Welcome

Sign in to continue

{/* Option 1: Clerk's pre-built button */} {/* Option 2: Custom button with openSignIn() */} {/* */}
) } /** * Authenticated View */ return (

Dashboard

{/* Clerk's pre-built user button (profile + sign out) */}

User Information

User ID
{userId}
Email
{user.primaryEmailAddress?.emailAddress}
Name
{user.firstName} {user.lastName}
{/* Access public metadata */} {user.publicMetadata && Object.keys(user.publicMetadata).length > 0 && (
Metadata
                    {JSON.stringify(user.publicMetadata, null, 2)}
                  
)}
{/* Example: Call protected API */} {/* Custom sign out button */}
) } /** * Example Component: Calling Protected API */ function ProtectedAPIExample({ getToken }: { getToken: () => Promise }) { const [data, setData] = React.useState(null) const [loading, setLoading] = React.useState(false) const [error, setError] = React.useState(null) const fetchProtectedData = async () => { setLoading(true) setError(null) try { // Get fresh session token (auto-refreshes) const token = await getToken() if (!token) { throw new Error('No session token available') } // Call your API with Authorization header const response = await fetch('https://your-worker.workers.dev/api/protected', { headers: { 'Authorization': `Bearer ${token}`, }, }) if (!response.ok) { throw new Error(`API error: ${response.status}`) } const result = await response.json() setData(result) } catch (err: any) { setError(err.message) } finally { setLoading(false) } } return (

Protected API Call

{error && (
Error: {error}
)} {data && (
            {JSON.stringify(data, null, 2)}
          
)}
) } export default App /** * Troubleshooting: * * 1. "Missing Publishable Key" error? * - Check .env.local has VITE_CLERK_PUBLISHABLE_KEY * - Restart dev server after adding env var * * 2. Flash of unauthenticated content? * - Always check isLoaded before rendering * - Show loading state while isLoaded is false * * 3. Token not working with API? * - Ensure getToken() is called fresh (don't cache) * - Check Authorization header format: "Bearer " * - Verify API is using @clerk/backend to verify token */