Install
npx expo install expo-cameraScanner example
Restrict barcodeTypes to 'qr' and debounce so one code fires the callback once:
// npx expo install expo-camera
import { useState } from 'react';
import { Text, View } from 'react-native';
import { CameraView, useCameraPermissions } from 'expo-camera';
function QRScanner({ onScan }) {
const [permission, requestPermission] = useCameraPermissions();
const [scanned, setScanned] = useState(false);
if (!permission) return <View />; // still loading
if (!permission.granted) {
requestPermission();
return <Text style={{ padding: 24 }}>Camera permission needed to scan.</Text>;
}
return (
<CameraView
style={{ flex: 1 }}
barcodeScannerSettings={{ barcodeTypes: ['qr'] }}
onBarcodeScanned={
scanned
? undefined // stop after one scan
: ({ data }) => { setScanned(true); onScan(data); }
}
/>
);
}Props (CameraView)
| Prop | Type | Default | Description |
|---|---|---|---|
| barcodeScannerSettings | object | — | Set { barcodeTypes: ['qr'] } to scan only QR. |
| onBarcodeScanned | fn | — | Fires with { data, type } on each detection. |
| facing | 'back'|'front' | 'back' | Which camera to use. |
| enableTorch | boolean | false | Flashlight for low light. |
Gotchas
onBarcodeScannedfires many times per second. Debounce with ascannedflag or you’ll trigger navigation dozens of times.- Handle all three permission states: still-loading (
!permission), denied, and granted. Skipping the loading state crashes. - The camera doesn’t work in the iOS simulator or web preview — test on a real device.
- Add the camera usage string to
app.json(expo-cameraplugin) or the build is rejected by the stores.
FAQ
How do I scan a QR code in React Native? Use expo-camera’s CameraView with onBarcodeScanned and barcodeTypes: ['qr'].
Why does my scanner fire repeatedly? Because the camera detects the code every frame — gate the callback with a one-time scanned flag.