React Native Hooks¶
The @moveris/react-native package provides 5 hooks for building custom native liveness verification UIs.
In plain terms
Hooks for building your own mobile UI while the SDK handles the logic: useLiveness for the full flow, useCamera for camera access, useFrameProcessor for frame processing, useFaceDetection for face detection, and useSmartFrameCapture for quality-gated capture.
Optional parameters
Parameters followed by ? (for example, options?) are optional. You can omit them if you don't need to customize the call. For instance, useLiveness() works without passing options.
Import¶
import {
useLiveness,
useCamera,
useFrameProcessor,
useFaceDetection,
useSmartFrameCapture,
} from '@moveris/react-native';
useLiveness¶
The main hook that manages the full liveness verification flow: camera access, frame capture, API submission, and result handling.
const {
state,
result,
error,
errorCode,
errorMessage,
progress,
start,
stop,
reset,
} = useLiveness(options?);
Options¶
| Option | Type | Default | Description |
|---|---|---|---|
model | FastCheckModel | DEFAULT_MODEL (mixed-30-v3_1_1) | Model to use |
source | FrameSource | 'live' | Frame source |
sessionId | string | auto-generated | Optional. Session ID for API calls. When provided, the same ID is used for every request in the session. |
endpoint | 'fast-check' \| 'fast-check-stream' \| 'hybrid-50' \| 'hybrid-150' \| 'verify' | 'fast-check-stream' | API endpoint |
sequentialStreaming | boolean | false | When endpoint is fast-check-stream, send one frame at a time |
frameCount | number | from model | Frames to capture (30, 60, or 120) |
onResult | (result: LivenessResult) => void | -- | Result callback |
onError | (error: Error) => void | -- | Error callback |
onProgress | (received: number, total: number) => void | -- | Progress callback |
Return Value¶
| Property | Type | Description |
|---|---|---|
state | 'idle' \| 'capturing' \| 'uploading' \| 'processing' \| 'complete' \| 'error' | Current state |
result | LivenessResult \| null | Verification result |
error | Error \| null | Error if failed |
errorCode | string \| null | API error code when the error is a LivenessApiError |
errorMessage | string \| null | User-facing error message |
progress | { current: number; total: number } | Frames captured so far and frames required |
start | () => void | Start the flow |
stop | () => void | Stop capturing |
reset | () => void | Reset to idle |
captureFrame | (base64Data: string) => void | Push a captured frame into the session |
Example¶
function CustomLivenessScreen() {
const {
state,
result,
progress,
start,
reset,
} = useLiveness({
endpoint: 'fast-check-stream',
onResult: (r) => Alert.alert('Result', r.verdict),
});
return (
<View style={{ flex: 1, justifyContent: 'center', padding: 20 }}>
<Text>Status: {state}</Text>
<Text>Frames: {progress.current}/{progress.total}</Text>
{state === 'idle' && (
<Button title="Start" onPress={start} />
)}
{result && <Text>Verdict: {result.verdict}</Text>}
{(result || state === 'error') && (
<Button title="Retry" onPress={reset} />
)}
</View>
);
}
useCamera¶
Manages camera permission. Pair it with Vision Camera's useCameraDevice for the device object.
const {
permissionStatus,
checkPermission,
requestPermission,
openSettings,
isActive,
error,
start,
stop,
} = useCamera(options?);
Options¶
| Option | Type | Default | Description |
|---|---|---|---|
checkPermission | () => CameraPermissionStatus \| Promise<CameraPermissionStatus> | -- | Pass Camera.getCameraPermissionStatus |
requestPermission | () => Promise<CameraPermissionStatus> | -- | Pass Camera.requestCameraPermission |
Return Value¶
| Property | Type | Description |
|---|---|---|
permissionStatus | 'granted' \| 'denied' \| 'not-determined' \| 'restricted' \| 'limited' | Camera permission |
checkPermission | () => Promise<CameraPermissionStatus> | Read permission without prompting |
requestPermission | () => Promise<CameraPermissionStatus> | Request camera permission |
openSettings | () => Promise<void> | Open device settings when permission is denied |
isActive | boolean | Whether the hook considers the camera active |
error | Error \| null | Camera error |
start | () => Promise<void> | Mark the camera active |
stop | () => void | Mark the camera inactive |
Example¶
import { Camera, useCameraDevice } from 'react-native-vision-camera';
import { useCamera } from '@moveris/react-native';
function CameraPreview() {
const device = useCameraDevice('front');
const { permissionStatus, requestPermission } = useCamera({
checkPermission: Camera.getCameraPermissionStatus,
requestPermission: Camera.requestCameraPermission,
});
if (permissionStatus !== 'granted') {
return <Button title="Enable Camera" onPress={requestPermission} />;
}
if (!device) {
return <ActivityIndicator />;
}
return (
<Camera
style={{ flex: 1 }}
device={device}
isActive={true}
/>
);
}
useFrameProcessor¶
Integration with Vision Camera's frame processor for real-time frame handling.
Options¶
| Option | Type | Default | Description |
|---|---|---|---|
onFrame | (frame: CapturedFrame) => void | required | Called after each accepted frame |
enabled | boolean | true | Whether processing is active |
fps | number | 30 | Target capture FPS |
Return Value¶
| Property | Type | Description |
|---|---|---|
processFrame | (base64Data: string) => void | Call from a Vision Camera worklet via runOnJS |
isEnabled | boolean | Whether processing is active |
enable | () => void | Start accepting frames |
disable | () => void | Stop accepting frames |
Example¶
import { Camera, useCameraDevice, useFrameProcessor } from 'react-native-vision-camera';
import { useFrameProcessor as useMoverisFrameProcessor } from '@moveris/react-native';
import { runOnJS } from 'react-native-reanimated';
function ProcessorCapture() {
const device = useCameraDevice('front');
const { processFrame, isEnabled } = useMoverisFrameProcessor({
fps: 30,
onFrame: (frame) => {
console.log('Captured frame', frame.index);
},
});
const frameProcessor = useFrameProcessor((frame) => {
'worklet';
if (isEnabled) {
const base64 = convertFrameToBase64(frame);
runOnJS(processFrame)(base64);
}
}, [isEnabled, processFrame]);
if (!device) return null;
return (
<Camera
style={{ flex: 1 }}
device={device}
isActive={true}
frameProcessor={frameProcessor}
/>
);
}
convertFrameToBase64 is your worklet encoder. The SDK does not ship one.
useFaceDetection¶
Adapts ML Kit or Expo Face Detector results into the SDK face box format.
Options¶
| Option | Type | Default | Description |
|---|---|---|---|
adapter | FaceDetectorAdapter | -- | Optional detector (createMLKitAdapter() or createExpoFaceDetectorAdapter()) |
Adapters¶
ML Kit (Recommended for bare React Native)¶
import { createMLKitAdapter } from '@moveris/react-native';
const adapter = createMLKitAdapter({
performanceMode: 'fast',
landmarkMode: 'all',
classificationMode: 'all',
});
Expo Face Detector¶
import { createExpoFaceDetectorAdapter } from '@moveris/react-native';
const adapter = createExpoFaceDetectorAdapter({
mode: 'fast',
detectLandmarks: true,
runClassifications: true,
});
Return Value¶
| Property | Type | Description |
|---|---|---|
isReady | boolean | Whether the adapter is ready |
processFrame | (frame, frameInfo) => FaceDetectionResult | Run detection on a camera frame |
lastResult | FaceDetectionResult \| null | Last detection result |
convertDetection | (detection, width, height) => FaceDetectionResult | Convert an external detection into SDK format |
Example¶
function FaceDetectionStatus() {
const { isReady, lastResult } = useFaceDetection({
adapter: createMLKitAdapter(),
});
if (!isReady) return <Text>Loading face detector...</Text>;
return (
<Text>
{lastResult?.detected ? 'Face detected' : 'No face detected'}
</Text>
);
}
useSmartFrameCapture¶
Intelligent frame capture that only counts frames when quality thresholds are met. Feed each camera frame into onFrameProcessed.
const {
state,
frames,
progress,
quality,
ovalState,
feedback,
canCapture,
start,
stop,
reset,
onFrameProcessed,
} = useSmartFrameCapture(options);
Options¶
| Option | Type | Default | Description |
|---|---|---|---|
targetFrames | number | 10 | Pass 30, 60, or 120 to match the model. The hook default is 10, which the API rejects. |
onComplete | (frames: CapturedFrame[]) => void | -- | Called when all frames are captured |
onError | (error: Error) => void | -- | Error callback |
onQualityUpdate | (quality) => void | -- | Called on each quality update |
cropFace | (frameBase64, faceBox, width, height) => Promise<string \| null> | identity | Optional crop function for fast-check-crops |
Return Value¶
| Property | Type | Description |
|---|---|---|
state | 'idle' \| 'capturing' \| 'complete' \| 'error' | Capture state |
frames | CapturedFrame[] | Captured frames |
progress | { captured: number; target: number; highQuality: number; goodQuality: number } | Capture progress |
quality | SmartCaptureQuality | Latest quality sample |
ovalState | OvalGuideState | Guide visual state |
feedback | string | User-facing guidance |
canCapture | boolean | Whether the current frame would be accepted |
start | () => void | Start smart capture |
stop | () => void | Pause capture |
reset | () => void | Reset and clear frames |
onFrameProcessed | (frameData, faceDetections) => Promise<void> | Call this for every camera frame |
Example¶
function SmartCapture() {
const {
state,
progress,
feedback,
start,
reset,
onFrameProcessed,
} = useSmartFrameCapture({
targetFrames: 30,
onComplete: (frames) => {
console.log('All frames captured:', frames.length);
},
});
return (
<View style={{ flex: 1, padding: 20 }}>
{feedback ? (
<Text style={{ fontSize: 16, color: '#3b82f6', textAlign: 'center' }}>
{feedback}
</Text>
) : null}
<Text>Frames: {progress.captured}/{progress.target}</Text>
{state === 'idle' && (
<Button title="Start Smart Capture" onPress={start} />
)}
{state === 'complete' && (
<Button title="Retry" onPress={reset} />
)}
</View>
);
}
Differences from React (Web) Hooks¶
| Feature | React (Web) | React Native |
|---|---|---|
| Camera | useCamera returns a MediaStream; attach it to a <video> | useCamera is permission-only; pair it with Vision Camera useCameraDevice |
| Frame capture | useFrameCapture reads a <video> | useFrameProcessor + runOnJS(processFrame); the SDK does not ship a frame encoder |
| Face detection | detect(video) on an HTMLVideoElement | processFrame / convertDetection on camera frames |
| Smart capture | videoRef required | onFrameProcessed per camera frame; no videoRef |
| Styles | CSS / CSSProperties | StyleSheet / ViewStyle |
| Button events | onClick | onPress |
useLiveness shares state, progress, start, stop, and reset on both platforms. Camera, face detection, and smart capture do not. Copy from the page that matches your package.