Skip to content

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.

const {
  processFrame,
  isEnabled,
  enable,
  disable,
} = useFrameProcessor(options?);

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.

const {
  isReady,
  processFrame,
  lastResult,
  convertDetection,
} = useFaceDetection(options?);

Options

Option Type Default Description
adapter FaceDetectorAdapter -- Optional detector (createMLKitAdapter() or createExpoFaceDetectorAdapter())

Adapters

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.