1. React Native
  2. Camera Switching

React Native

Camera Switching

The Vision SDK supports switching between front and back cameras on supported devices. Camera switching is driven declaratively through the cameraFacing prop on VisionCamera.

INFO

Platform Support (as of v3.12.0)

  • iOS: Fully functional - a live in-place input swap on the running session
  • Android: Fully functional - the camera session is rebuilt around the new facing

Both platforms apply the cameraFacing prop for real. The remaining difference is how: iOS swaps the input on the existing session, Android stops and restarts the camera with the new facing, so Android shows a brief preview gap on switch. Read state.facing back from onCameraStateChanged rather than assuming the prop took effect instantly.


Switching with cameraFacing

Set the cameraFacing prop to 'back' or 'front' and the camera moves to that facing. There is no ref method for switching cameras.

Basic Implementation

        import React, { useState, useRef } from 'react';
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
import { VisionCamera, VisionCameraRefProps, CameraFacing } from 'react-native-vision-sdk';

function CameraSwitchExample() {
  const cameraRef = useRef<VisionCameraRefProps>(null);
  const [cameraFacing, setCameraFacing] = useState<CameraFacing>('back');

  const toggleCamera = () => {
    setCameraFacing(prev => prev === 'back' ? 'front' : 'back');
  };

  return (
    <View style={styles.container}>
      <VisionCamera
        ref={cameraRef}
        scanMode="barcode"
        cameraFacing={cameraFacing}
        onBarcodeDetected={(event) => {
          console.log('Barcode detected:', event.codes);
        }}
      />

      <TouchableOpacity
        style={styles.switchButton}
        onPress={toggleCamera}
      >
        <Text style={styles.switchText}>
           Switch to {cameraFacing === 'back' ? 'Front' : 'Back'} Camera
        </Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1
  },
  switchButton: {
    position: 'absolute',
    top: 20,
    right: 20,
    backgroundColor: 'rgba(0, 0, 0, 0.7)',
    paddingHorizontal: 20,
    paddingVertical: 10,
    borderRadius: 20,
  },
  switchText: {
    color: 'white',
    fontSize: 14,
    fontWeight: '600',
  },
});

      

Props

Prop Type Default Description
cameraFacing 'back' | 'front' 'back' Camera facing direction

Type Export

        import { CameraFacing } from 'react-native-vision-sdk';
// CameraFacing = 'back' | 'front'

      

Advanced Examples

Camera Toggle Icon Overlaid on the Preview

VisionCamera accepts children, so a toggle control can be rendered directly on top of the preview:

        import React, { useState } from 'react';
import { Text, TouchableOpacity } from 'react-native';
import { VisionCamera } from 'react-native-vision-sdk';
import type { CameraFacing } from 'react-native-vision-sdk';

function CameraWithToggleIcon() {
  const [cameraFacing, setCameraFacing] = useState<CameraFacing>('back');

  return (
    <VisionCamera
      scanMode="photo"
      cameraFacing={cameraFacing}
      style={{ flex: 1 }}
    >
      <TouchableOpacity
        style={{
          position: 'absolute',
          top: 50,
          right: 20,
          width: 50,
          height: 50,
          borderRadius: 25,
          backgroundColor: 'rgba(0, 0, 0, 0.5)',
          justifyContent: 'center',
          alignItems: 'center',
        }}
        onPress={() =>
          setCameraFacing((prev) => (prev === 'back' ? 'front' : 'back'))
        }
      >
        <Text style={{ color: 'white', fontSize: 20 }}>Flip</Text>
      </TouchableOpacity>
    </VisionCamera>
  );
}

      

Platform-Specific Behavior

iOS

On iOS, camera switching works seamlessly:

  • Instant switching between cameras - the input is swapped in place on the running session
  • Maintains current scanning mode and settings
  • No frame drops during transition
  • Works with all scan modes (barcode, QR, OCR, photo)
        // iOS - Full support
<VisionCamera
  scanMode="barcode"
  cameraFacing={cameraFacing}
  onBarcodeDetected={handleBarcode}
/>

      

Android

On Android, camera switching is fully functional:

  • The prop is applied to the underlying camera settings and takes effect
  • Maintains current scanning mode and settings
  • The camera session is stopped and restarted on the new facing, so expect a brief preview gap rather than an instant swap
  • Works with all scan modes (barcode, QR, OCR, photo)
        // Android - Full support
<VisionCamera
  scanMode="barcode"
  cameraFacing={cameraFacing}
  onBarcodeDetected={handleBarcode}
/>

      
WARNING

A facing switch resets pinnedLensId on Android. A pin is facing-specific, so a genuine facing change drops the lens selection back to Auto. Do not drive cameraFacing and pinnedLensId together - see Camera Controls for the full comparison.


Best Practices

  1. Always provide a UI control for camera switching - don't make users guess:

            <TouchableOpacity onPress={toggleCamera}>
      <Text>Switch Camera</Text>
    </TouchableOpacity>
    
          
  2. Show current camera state to the user:

            <Text>Current: {cameraFacing === 'back' ? 'Back' : 'Front'} Camera</Text>
    
          
  3. Confirm the switch instead of assuming it. Both platforms apply the prop, but Android restarts the session to do it, so the preview is briefly down. Drive your UI off the camera's reported facing rather than off local state alone - and do not gate the control by platform:

            <VisionCamera
      cameraFacing={cameraFacing}
      onCameraStateChanged={(event) => setActualFacing(event.facing)}
    />
    <TouchableOpacity onPress={toggleCamera}>
      <Text>Switch (currently {actualFacing})</Text>
    </TouchableOpacity>
    
          
  4. Preserve other camera settings when switching:

            // VisionCamera - settings preserved automatically by props
    <VisionCamera
      cameraFacing={cameraFacing}
      torch={flash}
      zoomRatio={zoom}
    />
    
          

Troubleshooting

Camera doesn't switch

  • Verify the prop/method value is actually changing
  • Check device has both front and back cameras
  • Ensure camera permissions are granted for both cameras
  • Confirm you are on v3.12.0 or later, and check state.facing from onCameraStateChanged to see what the camera actually settled on

Switching stops working once a lens is pinned

  • On Android, a facing switch drops pinnedLensId back to Auto; a resolved pin also overrides cameraFacing and moves the camera to the pinned lens's facing
  • Drive one control or the other, not both - see Camera Controls

Brief preview gap during switch on Android

  • Expected - Android rebuilds the camera session for the new facing
  • Do not add your own stop()/start() around the switch; that competes with the rebuild

Camera feed freezes during switch

  • This shouldn't happen on iOS - report as a bug
  • Ensure you're not stopping/starting the camera during switch

Flash doesn't work on front camera

  • Most devices don't have front-facing flash
  • Consider adding a white screen flash effect for selfies