Skip to main content

DialstackComponentsProvider

The provider makes the DialStack instance and client secret available to all child components.

Usage

TypeScript
import { initialize } from '@dialstack/sdk-js';
import { DialstackComponentsProvider } from '@dialstack/sdk-react';

const dialstack = initialize({
publishableKey: 'pk_live_YOUR_KEY',
});

function App() {
return (
<DialstackComponentsProvider dialstack={dialstack} clientSecret="cs_live_...">
<YourApp />
</DialstackComponentsProvider>
);
}

Props

PropTypeRequiredDescription
dialstackDialStackInstanceYesInstance from initialize()
clientSecretstring | ClientSecretResponseYesSession token from your backend
childrenReactNodeYesChild components

clientSecret

The clientSecret prop accepts either a string or the full session response object:

TypeScript
// String only - you handle refresh
<DialstackComponentsProvider
dialstack={dialstack}
clientSecret="cs_live_abc123..."
>

// Full response - SDK handles refresh automatically
<DialstackComponentsProvider
dialstack={dialstack}
clientSecret={{
client_secret: "cs_live_abc123...",
expires_at: "2025-01-15T12:00:00Z"
}}
>

useDialstackComponents Hook

Access the provider context in child components:

TypeScript
import { useDialstackComponents } from '@dialstack/sdk-react';

function StatusIndicator() {
const { dialstack, clientSecret } = useDialstackComponents();

return <div>{clientSecret ? 'Connected' : 'Not connected'}</div>;
}

Return Value

TypeScript
interface UseDialstackComponentsReturn {
dialstack: DialStackInstance;
clientSecret: string | ClientSecretResponse;
}

Error: Missing Provider

If you use a component outside the provider, you'll see this error:

Text
Error: Could not find DialStack context; You need to wrap your app
in a <DialstackComponentsProvider> provider.
See https://docs.dialstack.ai/sdks/react for setup instructions.

Fix: Wrap your component tree with the provider:

TypeScript
// Before (error)
function App() {
return <CallLogs />;
}

// After (working)
function App() {
return (
<DialstackComponentsProvider dialstack={dialstack} clientSecret={secret}>
<CallLogs />
</DialstackComponentsProvider>
);
}

Multiple Providers

You can use multiple providers for different accounts:

TypeScript
function MultiAccountDashboard() {
return (
<div>
<DialstackComponentsProvider dialstack={dialstack} clientSecret={accountASecret}>
<h2>Account A</h2>
<CallLogs />
</DialstackComponentsProvider>

<DialstackComponentsProvider dialstack={dialstack} clientSecret={accountBSecret}>
<h2>Account B</h2>
<CallLogs />
</DialstackComponentsProvider>
</div>
);
}

Complete Example

TypeScript
import { useState, useEffect } from 'react';
import { initialize } from '@dialstack/sdk-js';
import { DialstackComponentsProvider } from '@dialstack/sdk-react';
import { CallLogs } from '@dialstack/sdk-react/call-logs';
import { Voicemails } from '@dialstack/sdk-react/voicemails';

const dialstack = initialize({
publishableKey: 'pk_live_YOUR_KEY',
appearance: {
theme: 'auto',
variables: {
colorPrimary: '#6772E5',
},
},
});

interface Session {
client_secret: string;
expires_at: string;
}

function App() {
const [session, setSession] = useState<Session | null>(null);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
async function fetchSession() {
try {
const response = await fetch('/api/dialstack/session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ accountId: 'acct_123' }),
});

if (!response.ok) {
throw new Error('Failed to create session');
}

const data = await response.json();
setSession(data);
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error');
}
}

fetchSession();
}, []);

if (error) {
return <div>Error: {error}</div>;
}

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

return (
<DialstackComponentsProvider dialstack={dialstack} clientSecret={session}>
<div className="dashboard">
<h1>Voice Dashboard</h1>
<CallLogs />
<Voicemails userId="user_123" />
</div>
</DialstackComponentsProvider>
);
}

export default App;

Handling API errors

Calls made through the instance reject with an ApiError, which carries the HTTP status and, when the API returns one, a machine-readable code. Use isApiError to narrow an unknown error:

TypeScript
import { isApiError } from '@dialstack/sdk-js';

try {
await dialstack.phoneNumbers.list({ limit: 20 });
} catch (err) {
if (isApiError(err)) {
if (err.status === 401) {
// Session expired — mint a new client secret
}
console.error(err.status, err.code, err.message);
} else {
throw err;
}
}

Prefer isApiError(err) over err instanceof ApiError. The error is created inside @dialstack/sdk-js but caught in your code, and instanceof compares against one specific class, so it can return false even for a genuine API error — for example when the error crosses an iframe or worker boundary, or when more than one copy of the package ends up installed. isApiError checks the error's own fields instead, so it holds in those cases. The ApiError class is still exported if you need it for other purposes.

Next Steps