React Hooks
The Raptor SDK includes React hooks for managing document processing state, auto-link settings, and real-time updates in your React applications.The SDK must be used server-side only. Never expose your API key in client-side code. Use React hooks in Server Components or with server-side API routes.
Installation
The React hooks are included with the SDK:Copy
npm install @raptor-data/ts-sdk
Available Hooks
useProcessingStatus
Monitor document processing status in real-time:Copy
import { useProcessingStatus } from '@raptor-data/ts-sdk/hooks';
import Raptor from '@raptor-data/ts-sdk';
const raptor = new Raptor({ apiKey: process.env.RAPTOR_API_KEY });
function DocumentStatus({ variantId }: { variantId: string }) {
const { variant, loading, error, refetch } = useProcessingStatus(raptor, variantId, {
pollInterval: 2000, // Poll every 2 seconds
enabled: true // Auto-start polling
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h3>Processing Status</h3>
<p>Status: {variant?.status}</p>
<p>Chunks: {variant?.chunksCount || 0}</p>
<p>Tokens: {variant?.totalTokens || 0}</p>
{variant?.status === 'processing' && (
<div>
<p>Processing...</p>
<button onClick={refetch}>Check Now</button>
</div>
)}
{variant?.status === 'completed' && (
<p>✓ Processing complete!</p>
)}
{variant?.status === 'failed' && (
<p>✗ Failed: {variant.error}</p>
)}
</div>
);
}
Polling interval in milliseconds
Whether to start polling automatically
Callback when processing completes
Callback when processing fails
useAutoLinkSettings
Manage auto-linking preferences:Copy
import { useAutoLinkSettings } from '@raptor-data/ts-sdk/hooks';
function AutoLinkSettings() {
const { settings, loading, error, updateSettings } = useAutoLinkSettings(raptor);
if (loading) return <p>Loading settings...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h3>Auto-Link Settings</h3>
<label>
<input
type="checkbox"
checked={settings?.autoLinkEnabled || false}
onChange={(e) => updateSettings({
autoLinkEnabled: e.target.checked
})}
/>
Enable Auto-Linking
</label>
<label>
Confidence Threshold: {settings?.autoLinkThreshold || 0.85}
<input
type="range"
min="0.5"
max="1.0"
step="0.05"
value={settings?.autoLinkThreshold || 0.85}
onChange={(e) => updateSettings({
autoLinkThreshold: parseFloat(e.target.value)
})}
/>
</label>
<p>
Current threshold: {((settings?.autoLinkThreshold || 0.85) * 100).toFixed(0)}%
</p>
</div>
);
}
useDocumentUpload
Handle file uploads with progress tracking:Copy
import { useDocumentUpload } from '@raptor-data/ts-sdk/hooks';
function DocumentUploader() {
const { upload, uploading, progress, result, error } = useDocumentUpload(raptor);
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const uploadResult = await upload(file, {
chunkSize: 512,
versionLabel: 'New Upload'
});
console.log('Upload complete:', uploadResult);
};
return (
<div>
<input
type="file"
onChange={handleFileChange}
disabled={uploading}
/>
{uploading && (
<div>
<p>Uploading... {progress}%</p>
<progress value={progress} max={100} />
</div>
)}
{result && (
<div>
<p>✓ Upload complete!</p>
<p>Document ID: {result.documentId}</p>
<p>Chunks: {result.chunks?.length || 0}</p>
{result.autoLinked && (
<p>
Auto-linked with {(result.autoLinkConfidence * 100).toFixed(0)}% confidence
</p>
)}
</div>
)}
{error && (
<p>✗ Error: {error.message}</p>
)}
</div>
);
}
useDocumentList
Fetch and display user’s documents:Copy
import { useDocumentList } from '@raptor-data/ts-sdk/hooks';
function DocumentList() {
const { documents, loading, error, refetch, hasMore, loadMore } = useDocumentList(raptor, {
limit: 20,
offset: 0
});
if (loading) return <p>Loading documents...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h3>Your Documents ({documents.length})</h3>
<button onClick={refetch}>Refresh</button>
<ul>
{documents.map(doc => (
<li key={doc.id}>
<strong>{doc.filename}</strong>
<p>Status: {doc.status}</p>
<p>Chunks: {doc.chunksCount}</p>
<p>Uploaded: {new Date(doc.createdAt).toLocaleDateString()}</p>
</li>
))}
</ul>
{hasMore && (
<button onClick={loadMore}>Load More</button>
)}
</div>
);
}
Complete Examples
Document Upload Flow
Copy
'use client';
import { useState } from 'react';
import { useDocumentUpload, useProcessingStatus } from '@raptor-data/ts-sdk/hooks';
import Raptor from '@raptor-data/ts-sdk';
// Initialize client (server-side only!)
const raptor = new Raptor({ apiKey: process.env.RAPTOR_API_KEY });
export function DocumentUploadFlow() {
const [variantId, setVariantId] = useState<string | null>(null);
const { upload, uploading, error: uploadError } = useDocumentUpload(raptor);
const { variant, loading } = useProcessingStatus(raptor, variantId, {
enabled: !!variantId,
pollInterval: 2000
});
const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const result = await upload(file, {
wait: false, // Don't wait for processing
chunkSize: 512,
versionLabel: file.name
});
if (result) {
setVariantId(result.variantId);
}
};
return (
<div>
<h2>Upload Document</h2>
<input
type="file"
onChange={handleUpload}
disabled={uploading}
/>
{uploading && <p>Uploading...</p>}
{uploadError && <p>Upload error: {uploadError.message}</p>}
{variantId && (
<div>
<h3>Processing Status</h3>
{loading && <p>Checking status...</p>}
{variant && (
<div>
<p>Status: <strong>{variant.status}</strong></p>
{variant.status === 'pending' && (
<p>⏳ Queued for processing...</p>
)}
{variant.status === 'processing' && (
<p>⚙️ Processing document...</p>
)}
{variant.status === 'completed' && (
<div>
<p>✓ Processing complete!</p>
<p>Chunks: {variant.chunksCount}</p>
<p>Tokens: {variant.totalTokens}</p>
</div>
)}
{variant.status === 'failed' && (
<p>✗ Failed: {variant.error}</p>
)}
</div>
)}
</div>
)}
</div>
);
}
Settings Panel
Copy
'use client';
import { useAutoLinkSettings } from '@raptor-data/ts-sdk/hooks';
import Raptor from '@raptor-data/ts-sdk';
const raptor = new Raptor({ apiKey: process.env.RAPTOR_API_KEY });
export function SettingsPanel() {
const { settings, loading, error, updateSettings } = useAutoLinkSettings(raptor);
if (loading) {
return <div>Loading settings...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div className="settings-panel">
<h2>Auto-Link Settings</h2>
<div className="setting">
<label>
<input
type="checkbox"
checked={settings?.autoLinkEnabled || false}
onChange={(e) => updateSettings({
autoLinkEnabled: e.target.checked
})}
/>
<span>Enable automatic version detection</span>
</label>
<p className="help-text">
Automatically detect when you're uploading a new version of an existing document.
</p>
</div>
<div className="setting">
<label>
<span>Confidence Threshold</span>
<input
type="range"
min="0.5"
max="1.0"
step="0.05"
value={settings?.autoLinkThreshold || 0.85}
onChange={(e) => updateSettings({
autoLinkThreshold: parseFloat(e.target.value)
})}
disabled={!settings?.autoLinkEnabled}
/>
<span className="threshold-value">
{((settings?.autoLinkThreshold || 0.85) * 100).toFixed(0)}%
</span>
</label>
<p className="help-text">
Minimum confidence required to auto-link documents. Higher values mean fewer false positives.
</p>
</div>
<div className="recommendation">
{settings?.autoLinkThreshold >= 0.95 && (
<p>Very conservative - only links with very high confidence</p>
)}
{settings?.autoLinkThreshold >= 0.85 && settings?.autoLinkThreshold < 0.95 && (
<p>Balanced - recommended for most use cases</p>
)}
{settings?.autoLinkThreshold < 0.85 && (
<p>Aggressive - may link unrelated documents</p>
)}
</div>
</div>
);
}
Document Browser
Copy
'use client';
import { useState } from 'react';
import { useDocumentList } from '@raptor-data/ts-sdk/hooks';
import Raptor from '@raptor-data/ts-sdk';
const raptor = new Raptor({ apiKey: process.env.RAPTOR_API_KEY });
export function DocumentBrowser() {
const [limit] = useState(20);
const [offset, setOffset] = useState(0);
const { documents, loading, error, refetch, hasMore } = useDocumentList(raptor, {
limit,
offset
});
const handlePrevious = () => {
setOffset(Math.max(0, offset - limit));
};
const handleNext = () => {
setOffset(offset + limit);
};
if (loading) {
return <div>Loading documents...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div className="document-browser">
<div className="header">
<h2>Documents</h2>
<button onClick={refetch}>Refresh</button>
</div>
<div className="document-grid">
{documents.map(doc => (
<div key={doc.id} className="document-card">
<h3>{doc.filename}</h3>
<div className="status">
<span className={`badge ${doc.status}`}>
{doc.status}
</span>
</div>
<div className="stats">
<div>
<strong>Chunks:</strong> {doc.chunksCount}
</div>
<div>
<strong>Tokens:</strong> {doc.totalTokens}
</div>
<div>
<strong>Size:</strong> {(doc.fileSizeBytes / 1024).toFixed(1)} KB
</div>
</div>
<div className="metadata">
<div>
<strong>Uploaded:</strong>{' '}
{new Date(doc.createdAt).toLocaleDateString()}
</div>
{doc.versionLabel && (
<div>
<strong>Version:</strong> {doc.versionLabel}
</div>
)}
</div>
</div>
))}
</div>
{documents.length === 0 && (
<div className="empty-state">
<p>No documents yet. Upload your first document to get started!</p>
</div>
)}
<div className="pagination">
<button
onClick={handlePrevious}
disabled={offset === 0}
>
Previous
</button>
<span>
Showing {offset + 1}-{offset + documents.length}
</span>
<button
onClick={handleNext}
disabled={!hasMore}
>
Next
</button>
</div>
</div>
);
}
Server-Side Usage
Next.js Server Component
Copy
// app/documents/page.tsx
import Raptor from '@raptor-data/ts-sdk';
const raptor = new Raptor({ apiKey: process.env.RAPTOR_API_KEY! });
export default async function DocumentsPage() {
const documents = await raptor.listDocuments({ limit: 20 });
return (
<div>
<h1>Documents</h1>
<ul>
{documents.map(doc => (
<li key={doc.id}>{doc.filename}</li>
))}
</ul>
</div>
);
}
Next.js API Route with Hook
Copy
// app/api/upload/route.ts
import Raptor from '@raptor-data/ts-sdk';
import { NextRequest } from 'next/server';
const raptor = new Raptor({ apiKey: process.env.RAPTOR_API_KEY! });
export async function POST(request: NextRequest) {
const formData = await request.formData();
const file = formData.get('file') as File;
const result = await raptor.process(file, {
wait: true
});
return Response.json({
documentId: result.documentId,
chunks: result.chunks.length
});
}
Best Practices
Server-side only: Never expose your API key in client-side code. Use Server Components or API routes.
Polling efficiently: Set appropriate poll intervals (2-5 seconds) to balance responsiveness and API usage.
Error handling: Always handle errors from hooks to provide good user experience.