React Integration
Integrate the VECU IDV Web SDK into your React applications with proper lifecycle management.
Basic Integration
import { useEffect, useRef } from 'react';
import { createVecuIDVSDK } from 'vec-idp-web-sdk';
function VerificationComponent({ customerInfo }) {
const containerRef = useRef<HTMLDivElement>(null);
const cleanupRef = useRef<(() => void) | null>(null);
useEffect(() => {
if (!customerInfo || !containerRef.current) return;
const sdk = createVecuIDVSDK({
deploymentStage: 'sandbox',
bearerToken: process.env.REACT_APP_BEARER_TOKEN,
debug: process.env.NODE_ENV === 'development',
logLevel: 'info',
});
sdk
.startVerificationWithCustomer(containerRef.current, {
customerInfo,
referenceId: `customer-${Date.now()}`,
mode: 'embedded',
onProgress: event => {
console.log(`Progress: ${event.step} (${event.percentage}%)`);
},
onSuccess: result => {
console.log('Verification completed!', result);
},
onError: error => {
console.error('Verification failed:', error);
},
config: {
qrCode: true,
},
})
.then(cleanup => {
cleanupRef.current = cleanup;
});
return () => {
cleanupRef.current?.();
sdk.destroy();
};
}, [customerInfo]);
return <div ref={containerRef} style={{ minHeight: '600px' }} />;
}
Custom Hook
Create a reusable hook for verification:
import { useEffect, useRef, useState, useCallback } from 'react';
import { createVecuIDVSDK, VecuIDVSDK } from 'vec-idp-web-sdk';
interface UseVerificationOptions {
onSuccess?: (result: any) => void;
onError?: (error: Error) => void;
onProgress?: (event: { step: string; percentage: number }) => void;
}
interface CustomerInfo {
firstName: string;
lastName: string;
email?: string;
phone?: string;
address?: {
line1: string;
locality: string;
majorAdminDivision: string;
country: string;
postalCode: string;
type: string;
};
}
export function useVerification(options: UseVerificationOptions = {}) {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const [result, setResult] = useState<any>(null);
const sdkRef = useRef<VecuIDVSDK | null>(null);
const cleanupRef = useRef<(() => void) | null>(null);
const containerRef = useRef<HTMLDivElement>(null);
// Initialize SDK
useEffect(() => {
sdkRef.current = createVecuIDVSDK({
deploymentStage:
process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',
bearerToken: process.env.REACT_APP_BEARER_TOKEN!,
debug: process.env.NODE_ENV === 'development',
});
return () => {
cleanupRef.current?.();
sdkRef.current?.destroy();
};
}, []);
const startVerification = useCallback(
async (customerInfo: CustomerInfo) => {
if (!sdkRef.current || !containerRef.current) return;
setIsLoading(true);
setError(null);
setResult(null);
try {
cleanupRef.current = await sdkRef.current.startVerificationWithCustomer(
containerRef.current,
{
customerInfo,
referenceId: `ref-${Date.now()}`,
onProgress: options.onProgress,
onSuccess: res => {
setResult(res);
setIsLoading(false);
options.onSuccess?.(res);
},
onError: err => {
setError(err);
setIsLoading(false);
options.onError?.(err);
},
config: {
qrCode: true,
},
}
);
} catch (err) {
setError(err as Error);
setIsLoading(false);
}
},
[options]
);
const cancelVerification = useCallback(() => {
cleanupRef.current?.();
setIsLoading(false);
}, []);
return {
containerRef,
startVerification,
cancelVerification,
isLoading,
error,
result,
};
}
Using the Hook
function VerificationPage() {
const {
containerRef,
startVerification,
cancelVerification,
isLoading,
error,
result,
} = useVerification({
onSuccess: result => {
console.log('Success!', result);
// Navigate to success page
},
onError: error => {
console.error('Error:', error);
},
});
const handleStart = () => {
startVerification({
firstName: 'John',
lastName: 'Doe',
email: 'john@example.com',
});
};
return (
<div>
<h1>Identity Verification</h1>
{error && <div className='error'>Error: {error.message}</div>}
{result && <div className='success'>Verification Complete!</div>}
<div ref={containerRef} style={{ minHeight: '600px' }} />
<div className='controls'>
<button onClick={handleStart} disabled={isLoading}>
{isLoading ? 'Verifying...' : 'Start Verification'}
</button>
{isLoading && <button onClick={cancelVerification}>Cancel</button>}
</div>
</div>
);
}
Next.js Integration
For Next.js applications, ensure the SDK is only loaded on the client:
'use client';
import { useEffect, useRef } from 'react';
import dynamic from 'next/dynamic';
function VerificationComponent({ customerInfo }) {
const containerRef = useRef<HTMLDivElement>(null);
const cleanupRef = useRef<(() => void) | null>(null);
useEffect(() => {
// Dynamic import to avoid SSR issues
import('vec-idp-web-sdk').then(({ createVecuIDVSDK }) => {
if (!containerRef.current) return;
const sdk = createVecuIDVSDK({
deploymentStage: 'sandbox',
bearerToken: process.env.NEXT_PUBLIC_BEARER_TOKEN!,
debug: true,
});
sdk
.startVerificationWithCustomer(containerRef.current, {
customerInfo,
referenceId: `ref-${Date.now()}`,
onSuccess: result => {
console.log('Success!', result);
},
onError: error => {
console.error('Error:', error);
},
})
.then(cleanup => {
cleanupRef.current = cleanup;
});
return () => {
cleanupRef.current?.();
sdk.destroy();
};
});
}, [customerInfo]);
return <div ref={containerRef} style={{ minHeight: '500px' }} />;
}
// Export with no SSR
export default dynamic(() => Promise.resolve(VerificationComponent), {
ssr: false,
});
Error Boundary
Wrap the verification component in an error boundary:
import { Component, ReactNode } from 'react';
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
}
class VerificationErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error('Verification error:', error, errorInfo);
// Log to error tracking service
}
render() {
if (this.state.hasError) {
return (
this.props.fallback || (
<div className='error-fallback'>
<h2>Verification Error</h2>
<p>Something went wrong. Please try again.</p>
<button onClick={() => this.setState({ hasError: false })}>
Retry
</button>
</div>
)
);
}
return this.props.children;
}
}
// Usage
function App() {
return (
<VerificationErrorBoundary>
<VerificationComponent customerInfo={customerInfo} />
</VerificationErrorBoundary>
);
}
Lazy Loading
Load the SDK only when needed to reduce initial bundle size:
import { lazy, Suspense } from 'react';
const VerificationComponent = lazy(() => import('./VerificationComponent'));
function App() {
const [showVerification, setShowVerification] = useState(false);
return (
<div>
<button onClick={() => setShowVerification(true)}>
Start Verification
</button>
{showVerification && (
<Suspense fallback={<div>Loading verification...</div>}>
<VerificationComponent customerInfo={customerInfo} />
</Suspense>
)}
</div>
);
}
TypeScript Types
The SDK includes TypeScript definitions. Import types as needed:
import {
createVecuIDVSDK,
VecuIDVSDKConfig,
VerificationOptions,
CustomerInfo,
VerificationResult,
} from 'vec-idp-web-sdk';
const config: VecuIDVSDKConfig = {
deploymentStage: 'sandbox',
bearerToken: 'your-token',
debug: true,
};
const sdk = createVecuIDVSDK(config);
Best Practices
- Always cleanup - Call the cleanup function when unmounting or when verification completes
- Use refs - Store SDK instance and cleanup function in refs to avoid re-initialization
- Handle errors - Implement proper error boundaries and error handling
- Lazy load - Only load the SDK when verification is needed
- Environment variables - Store tokens in environment variables, never in code
Next Steps
- Vue Integration - Vue.js integration guide
- API Reference - Complete method reference
- Events - Handle verification events