Skip to main content
The AuthContext provides authentication state management using Supabase Auth. It handles user sessions, automatic token refresh, and extended user information from the database.

Provider

AuthProvider

Wraps your application to provide authentication state to all child components.
children
React.ReactNode
required
The components that will have access to authentication context
App.tsx
import { AuthProvider } from './contexts/AuthContext';

function App() {
  return (
    <AuthProvider>
      <YourApp />
    </AuthProvider>
  );
}

Hook

useAuth()

Access authentication state and methods from any component within the AuthProvider.
Dashboard.tsx
import { useAuth } from './contexts/AuthContext';

export function Dashboard() {
  const { user, loading, signOut } = useAuth();

  if (loading) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>Welcome, {user?.nombre}</h1>
      <p>Role: {user?.userRole}</p>
      <button onClick={signOut}>Sign Out</button>
    </div>
  );
}

Context values

user
UserWithAttributes | null
The currently authenticated user with extended attributes from the database.
loading
boolean
true during initial session load or sign-in. Does not block UI during token refresh.
error
AuthError | null
Authentication error if one occurred during sign-in or session management
signOut
() => Promise<{ error: AuthError | null }>
Signs out the current user and clears the session
clearError
() => void
Clears the current error state

TypeScript types

AuthContextType

interface AuthContextType {
  user: UserWithAttributes | null;
  loading: boolean;
  signOut: () => Promise<{ error: AuthError | null }>;
  error: AuthError | null;
  clearError: () => void;
}

UserWithAttributes

type UserWithAttributes = Omit<User, 'deleted_at'> & {
  userRole?: string | null;
  idbu?: string | null;
  nombre?: string | null;
  estado?: string | null;
  deleted_at?: string | null;
};

Usage examples

Checking user role

ProtectedRoute.tsx
import { useAuth } from './contexts/AuthContext';
import { Navigate } from 'react-router-dom';

export function AdminRoute({ children }: { children: React.ReactNode }) {
  const { user, loading } = useAuth();

  if (loading) return <div>Loading...</div>;
  if (!user || user.userRole !== 'Administrador') {
    return <Navigate to="/" />;
  }

  return <>{children}</>;
}

Handling sign out

Header.tsx
import { useAuth } from './contexts/AuthContext';
import { useNavigate } from 'react-router-dom';

export function Header() {
  const { signOut, user } = useAuth();
  const navigate = useNavigate();

  const handleSignOut = async () => {
    const { error } = await signOut();
    if (error) {
      console.error('Sign out error:', error);
    } else {
      navigate('/login');
    }
  };

  return (
    <header>
      <span>{user?.nombre}</span>
      <button onClick={handleSignOut}>Sign Out</button>
    </header>
  );
}

Conditional rendering based on auth state

Prescriptions.tsx
import { useAuth } from './contexts/AuthContext';

export function Prescriptions() {
  const { user, loading } = useAuth();

  if (loading) {
    return <div>Loading prescriptions...</div>;
  }

  if (!user) {
    return <div>Please sign in to view prescriptions</div>;
  }

  return (
    <div>
      <h1>Prescriptions for {user.nombre}</h1>
      {/* Prescription list */}
    </div>
  );
}

Implementation details

Session management

  • The context automatically loads the user session on mount
  • Token refresh happens automatically in the background without blocking the UI
  • Extended user info (role, name, business unit) is fetched from tcUsuarios table
  • User info is cached to prevent redundant database queries

Loading states

  • loading is true during:
    • Initial session load (INITIAL_SESSION)
    • User sign-in (SIGNED_IN)
    • User sign-out (SIGNED_OUT)
  • loading remains false during token refresh to avoid UI flicker

Error handling

LoginForm.tsx
import { useAuth } from './contexts/AuthContext';
import { useEffect } from 'react';

export function LoginForm() {
  const { error, clearError } = useAuth();

  useEffect(() => {
    // Clear error when component unmounts
    return () => clearError();
  }, [clearError]);

  if (error) {
    return <div className="error">{error.message}</div>;
  }

  return <form>{/* Login form */}</form>;
}
For convenience, you can also import useAuth from the hooks directory:
import { useAuth } from '../hooks/useAuth';
// This re-exports the same hook from AuthContext

Build docs developers (and LLMs) love