Skip to main content

useApi

Access the configured API client for making HTTP requests.

Signature

function useApi(): Api

type Api = <T = any>(config: ApiConfig) => Promise<T>

interface ApiConfig {
  url: string;
  method?: 'get' | 'post' | 'put' | 'delete';
  data?: any;
  params?: Record<string, any>;
  headers?: Record<string, string>;
  silence?: boolean | boolean[];
  timeout?: number;
}

Returns

api
Api
Configured API client function for making HTTP requests

Usage

import { useApi } from '@proton/components';

function MyComponent() {
  const api = useApi();

  const fetchUser = async () => {
    const { User } = await api<{ User: User }>({
      url: '/core/v4/users',
      method: 'get'
    });
    return User;
  };

  return <div>...</div>;
}

Features

  • Type-safe responses with generics
  • Automatic authentication token injection
  • Error handling and retry logic
  • Request/response interceptors
  • Support for error silencing

useApiResult

Fetch data from an API endpoint with automatic loading and error state management.

Signature

function useApiResult<R, F extends QueryFunction = QueryFunction>(
  fn: QueryFunction,
  dependencies?: any[],
  throwOnError?: boolean,
  lazy?: boolean
): Result<R, Parameters<F>>

type QueryFunction = (...args: any[]) => { method: string; url: string }

interface Result<R, U extends any[]> {
  result: R | undefined;
  error: Error;
  loading: boolean;
  request: (...args: U) => Promise<R>;
}

Parameters

fn
QueryFunction
required
Query function that returns API config object
dependencies
any[]
Dependency array for automatic refetching
throwOnError
boolean
default:"true"
Whether to throw errors in render (for error boundaries)
lazy
boolean
default:"false"
If true, don’t fetch automatically on mount

Returns

result
R | undefined
The fetched data (undefined while loading or on error)
error
Error
Error object if request failed
loading
boolean
Whether the request is currently in progress
request
(...args: Parameters<F>) => Promise<R>
Function to manually trigger the request

Usage

import { useApiResult } from '@proton/components';
import { queryUserSettings } from '@proton/shared/lib/api/settings';

function SettingsComponent() {
  const { result: settings, loading, error } = useApiResult(
    queryUserSettings,
    [] // Empty array means fetch once on mount
  );

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return <div>{settings?.Theme}</div>;
}

Error Handling

// With error boundary (throwOnError: true)
try {
  return (
    <ErrorBoundary>
      <ComponentUsingApiResult />
    </ErrorBoundary>
  );
} catch (error) {
  // Error boundary catches the error
}

// Manual error handling (throwOnError: false)
const { error } = useApiResult(queryData, [], false);
if (error) {
  // Handle error in component
}

useCache

Access the application-wide cache for storing and retrieving data.

Signature

function useCache<K = string, V = any>(): Cache<K, V>

interface Cache<K, V> {
  get(key: K): V | undefined;
  set(key: K, value: V): void;
  has(key: K): boolean;
  delete(key: K): boolean;
  clear(): void;
  subscribe(callback: (key: K, value: V) => void): () => void;
}

Usage

import { useCache } from '@proton/components';

function MyComponent() {
  const cache = useCache();

  // Get cached value
  const user = cache.get('user');

  // Set cache value
  cache.set('user', { id: 1, name: 'John' });

  // Check if key exists
  if (cache.has('user')) {
    console.log('User is cached');
  }

  return <div>...</div>;
}

Cache Keys

Common cache keys used throughout Proton WebClients:
// User data
cache.get('user');
cache.get('addresses');
cache.get('user-settings');

// Organization
cache.get('organization');
cache.get('organization-key');

// Subscription
cache.get('subscription');
cache.get('plans');

// Mail
cache.get('mail-settings');
cache.get('labels');
cache.get('folders');

Best Practices

Always specify type parameters for type safety:
const cache = useCache<string, User>();
Always unsubscribe from cache changes:
useEffect(() => {
  const unsubscribe = cache.subscribe(handler);
  return unsubscribe;
}, []);
Always check if a value exists before using it:
const user = cache.get('user');
if (user) {
  // Use user safely
}

Next Steps

Build docs developers (and LLMs) love