useDeva
React hook for accessing authentication state and user information.
Import
import { useDeva } from "@bitplanet/deva-sdk";Relationship with DevaProvider
useDeva and DevaProvider work together as a React Context pattern:
DevaProvider (Component):
Wraps your application at the root level
Manages OAuth authentication flow
Handles token refresh automatically
Stores authentication state in React Context
Provides configuration (clientId, redirectUri, env)
useDeva (Hook):
Consumes the Context created by DevaProvider
Provides a simplified API for child components
Returns only essential properties for application use
Cannot be used outside of DevaProvider
Relationship:
<DevaProvider clientId="..." redirectUri="..." env="...">
{/* DevaProvider creates and manages auth state */}
<MyComponent />
{/* useDeva() accesses the auth state */}
</DevaProvider>Think of it as:
DevaProvider = Authentication engine (does the work)
useDeva = Dashboard (shows you the results)
Learn more about DevaProvider →
What It Does
Provides access to:
User authentication status
User profile information
Login/logout functions
Access token for API calls
Must be used inside a DevaProvider component.
Basic Usage
import { useDeva } from "@bitplanet/deva-sdk";
function MyComponent() {
const { isAuthenticated, user, login, logout } = useDeva();
if (!isAuthenticated) {
return <button onClick={login}>Login with Deva</button>;
}
return (
<div>
<p>Welcome, {user?.persona?.display_name}!</p>
<button onClick={logout}>Logout</button>
</div>
);
}Return Values
interface UseDevaReturn {
isAuthenticated: boolean; // Is user logged in?
isReady: boolean; // Is SDK initialized?
user: UserInfo | null; // User profile data
accessToken: string | null; // JWT token for API calls
login: () => Promise<void>; // Start login flow
logout: () => Promise<void>; // End session
}isAuthenticated
Type: boolean
Indicates whether the user is currently authenticated.
Values:
true- User has valid access tokenfalse- User not logged in or token expired
Usage: Check if user is logged in
const { isAuthenticated } = useDeva();
if (isAuthenticated) {
return <Dashboard />;
}
return <LoginPage />;isReady
Type: boolean Indicates whether the SDK has finished initializing.
Values:
true- SDK initialization complete, safe to check authenticationfalse- SDK still loading OpenID configuration
Usage: Check if SDK finished initializing
Important: Always check isReady before using isAuthenticated
const { isReady, isAuthenticated } = useDeva();
if (!isReady) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
return <LoginPage />;
}
return <App />;user
Type: UserInfo | null
Complete user information including profile and persona data.
Contains:
interface UserInfo {
sub: string; // User ID
preferred_username: string; // Username
email?: string; // Email
email_verified?: boolean; // Email verified?
picture?: string; // Profile picture URL
persona: {
id: string;
username: string;
display_name: string;
avatar: string;
bio?: string;
};
}Usage:
const { user } = useDeva();
return (
<div>
<img src={user?.persona.avatar} />
<h2>{user?.persona.display_name}</h2>
<p>@{user?.preferred_username}</p>
</div>
);accessToken
Type: string | null
The current OAuth access token.
Values:
JWT string when authenticated
nullwhen not authenticated
Usage: Include in API requests
const { accessToken } = useDeva();
// Use for custom API calls
if (accessToken) {
fetch("https://api.deva.me/custom", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
}Note: SDK components automatically include the token. You only need this for custom API calls.
login
Type: () => Promise<void>
Initiates the OAuth 2.0 authentication flow.
Usage: Initiate OAuth login flow
const { login } = useDeva();
<button onClick={login}>Sign in with Deva</button>What happens:
Redirects user to Deva login page
User authenticates
Redirects back to your app
SDK exchanges code for tokens
isAuthenticatedbecomestrue
logout
Type: () => Promise<void>
Revokes tokens and clears authentication state.
Usage: End user session
const { logout } = useDeva();
<button onClick={logout}>Logout</button>What happens:
Revokes tokens on server
Clears local session data
isAuthenticatedbecomesfalseuserbecomesnull
Common Patterns
Protected Route
function ProtectedRoute({ children }) {
const { isReady, isAuthenticated, login } = useDeva();
if (!isReady) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
return <button onClick={login}>Login Required</button>;
}
return <>{children}</>;
}User Profile Display
function UserProfile() {
const { user, isAuthenticated } = useDeva();
if (!isAuthenticated || !user) {
return null;
}
return (
<div>
<img src={user.persona.avatar} alt={user.preferred_username} />
<h3>{user.persona.display_name}</h3>
<p>@{user.preferred_username}</p>
{user.email_verified && <span>✓ Verified</span>}
</div>
);
}Login/Logout Toggle
function AuthButton() {
const { isAuthenticated, user, login, logout } = useDeva();
return isAuthenticated ? (
<button onClick={logout}>
Logout ({user?.preferred_username})
</button>
) : (
<button onClick={login}>Login</button>
);
}Custom API Call
function CustomData() {
const { accessToken, isAuthenticated } = useDeva();
const [data, setData] = useState(null);
const fetchData = async () => {
if (!isAuthenticated || !accessToken) return;
const response = await fetch("/api/custom", {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
setData(await response.json());
};
return <button onClick={fetchData}>Fetch Data</button>;
}Important Notes
Must Use Inside DevaProvider
// ❌ Error: useDeva must be used within a DevaProvider
function App() {
const { user } = useDeva(); // Will throw error
return <div>{user?.name}</div>;
}// ✅ Correct
import { DevaProvider } from "@bitplanet/deva-sdk";
function App() {
return (
<DevaProvider clientId="..." redirectUri="..." env="...">
<MyComponent /> {/* Can use useDeva here */}
</DevaProvider>
);
}Always Check isReady First
// ❌ Bad: May flash wrong state during initialization
const { isAuthenticated } = useDeva();
if (!isAuthenticated) return <Login />;// ✅ Good: Wait for SDK to initialize
const { isReady, isAuthenticated } = useDeva();
if (!isReady) return <Loading />;
if (!isAuthenticated) return <Login />;Handle Null User
// ✅ Use optional chaining
const displayName = user?.persona.display_name || "Guest";
const avatar = user?.picture || user?.persona.avatar || "/default.png";TypeScript
Full type definitions:
import { useDeva } from "@bitplanet/deva-sdk";
import type { UserInfo } from "@bitplanet/deva-sdk";
interface UseDevaReturn {
isAuthenticated: boolean;
isReady: boolean;
accessToken: string | null;
user: UserInfo | null;
login: () => Promise<void>;
logout: () => Promise<void>;
}
const useDeva: () => UseDevaReturn;Related Documentation
Last updated