Skip to content

React

The SDK ships a React wrapper at @checktiv/sdk-web/react. It provides:

  • ChecktivProvider - holds the ChecktivClient in React context. Wrap your app (or the subtree that needs verification) with this.
  • useChecktiv() - returns the ChecktivClient from context. Throws a clear error if called outside a provider.
  • ChecktivIdv - mounts the managed IDV module into a DOM node. Handles cleanup on unmount.

ChecktivIdv (and any direct mount('idv') call) renders the managed IDV module, which self-registers on import. Add a one-time side-effect import of @checktiv/sdk-web/idv in your app (for example next to ChecktivProvider) so the module is registered before the first mount. Without it the mount fails with sdk_load_failed.

Terminal window
npm install @checktiv/sdk-web react react-dom

react and react-dom are peer dependencies. The SDK does not bundle them.

import { ChecktivProvider, ChecktivIdv } from '@checktiv/sdk-web/react';
import '@checktiv/sdk-web/idv'; // registers the IDV module that ChecktivIdv mounts
export function App() {
return (
<ChecktivProvider
publishableKey="ah_pk_us_test_..."
getSessionToken={async (ctx) => {
const res = await fetch('/api/checktiv/token', {
method: 'POST',
body: JSON.stringify({ reason: ctx.reason }),
headers: { 'Content-Type': 'application/json' },
});
return (await res.json()).token;
}}
theme={{ primaryColor: '#0b5fff' }}
>
<VerificationPage />
</ChecktivProvider>
);
}
function VerificationPage() {
function handleEvent(event) {
if (event.type === 'checktiv.idv.submitted') {
// Capture complete. Wait for the webhook before acting on the outcome.
console.log('Verification submitted');
}
if (event.type === 'checktiv.idv.error') {
console.error('IDV error:', event.error);
}
}
return (
<div>
<h1>Verify your identity</h1>
<ChecktivIdv onEvent={handleEvent} />
</div>
);
}

ChecktivProvider is SSR-safe. On the server (Node.js / edge), init() detects the absence of window and returns null. The provider renders nothing server-side; the client is created and mounted only in the browser.

In Next.js, you do not need "use client" on ChecktivProvider itself - the wrapper handles the guard internally. You do need "use client" on any component that calls useChecktiv() directly or renders <ChecktivIdv> (because those depend on the browser DOM).

// app/verify/page.tsx (Server Component)
import { ChecktivProvider } from '@checktiv/sdk-web/react';
import { VerifyClient } from './VerifyClient';
export default function VerifyPage() {
return (
<ChecktivProvider publishableKey="ah_pk_us_test_..." getSessionToken={...}>
<VerifyClient />
</ChecktivProvider>
);
}
// app/verify/VerifyClient.tsx
'use client';
import { ChecktivIdv } from '@checktiv/sdk-web/react';
import '@checktiv/sdk-web/idv'; // registers the IDV module that ChecktivIdv mounts
export function VerifyClient() {
return <ChecktivIdv onEvent={(e) => console.log(e)} />;
}

ChecktivIdv calls handle.destroy() automatically when the component unmounts. You do not need to clean up manually. Under React’s StrictMode double-invoke, the component mounts, destroys, and remounts cleanly.

If you need the client for custom mount logic, call useChecktiv():

'use client';
import { useChecktiv } from '@checktiv/sdk-web/react';
import '@checktiv/sdk-web/idv'; // registers the IDV module that mount('idv') resolves
import { useEffect, useRef } from 'react';
export function CustomIdvMount() {
const client = useChecktiv();
const containerRef = useRef(null);
useEffect(() => {
if (!containerRef.current) return;
const handle = client.mount('idv', {
target: containerRef.current,
onEvent: (event) => console.log(event),
});
return () => handle.destroy();
}, [client]);
return <div ref={containerRef} />;
}

onEvent receives every checktiv.idv.* event:

Event type Meaning
checktiv.idv.ready The capture frame loaded and is ready for the applicant.
checktiv.idv.submitted The applicant finished capture. Terminal for capture; the verdict arrives via webhook.
checktiv.idv.error An error occurred. Check event.error.code and event.error.recovery.

Do not exhaustively switch on event.type. New event types may be added without a major version bump. Handle known types and ignore unknown ones.