Skip to content

React Native and Flutter barcode scanners: a practical guide

In React Native, use react-native-vision-camera's code scanner, or expo-camera's CameraView in an Expo app. In Flutter, use the mobile_scanner package. All three read QR codes and common barcodes from the live camera, and all three need a camera permission declared in your app.

Which package to use

Package APIs change between major versions. The lines below match current releases; if your installed version differs, its README is the source of truth.

  • Expo app, including Expo Go: expo-camera. Barcode scanning is built into its CameraView component.
  • React Native with a custom native build: react-native-vision-camera, whose useCodeScanner hook reads QR codes and barcodes.
  • Flutter: mobile_scanner, which uses Google's ML Kit on Android and supports iOS, and web and macOS in recent versions.
  • Avoid old tutorials built on react-native-camera, which is deprecated, and expo-barcode-scanner, which Expo deprecated in favour of expo-camera and has since removed from the SDK.

Expo QR code scanner with expo-camera

For a store build, add a camera permission message through the expo-camera config plugin in app.json, so iOS shows your reason when it asks.

  1. Install it with npx expo install expo-camera.
  2. Import the pieces: import { CameraView, useCameraPermissions } from 'expo-camera';
  3. In your component: const [permission, requestPermission] = useCameraPermissions();
  4. If permission is not granted, show a button that calls requestPermission().
  5. Render the camera: <CameraView style={{ flex: 1 }} facing="back" barcodeScannerSettings={{ barcodeTypes: ['qr', 'ean13', 'code128'] }} onBarcodeScanned={({ data }) => setResult(data)} />
  6. After a hit, set onBarcodeScanned to undefined (for example with a scanned flag in state), or it fires again on every frame the code stays in view.

React Native barcode scanner with react-native-vision-camera

VisionCamera is a full camera library with a built-in code scanner. It needs native code, so it runs in a development build rather than Expo Go.

Get the device and permission: const device = useCameraDevice('back'); and const { hasPermission, requestPermission } = useCameraPermission();

Create the scanner: const codeScanner = useCodeScanner({ codeTypes: ['qr', 'ean-13'], onCodeScanned: (codes) => console.log(codes[0]?.value) });

Render it: <Camera style={StyleSheet.absoluteFill} device={device} isActive={true} codeScanner={codeScanner} />

Set isActive to false when the screen is not focused, so the camera turns off when the user leaves. On Android the code scanner uses Google's ML Kit; the VisionCamera docs explain the Gradle setting that chooses between a bundled model and one downloaded through Google Play services.

On Android, Google also offers a ready-made code scanner screen through ML Kit, which does not need camera permission in your own app. It is Android-only, so it suits apps that only need to scan occasionally.

Flutter QR code and barcode scanner with mobile_scanner

Handle the case where rawValue is null: some barcodes contain binary data rather than text. As with the other packages, ignore repeat detections of the same value, or your navigation code will run several times.

  1. Add the package: flutter pub add mobile_scanner
  2. On iOS, add NSCameraUsageDescription to ios/Runner/Info.plist with a short reason, such as 'Used to scan QR codes'.
  3. Place the widget: MobileScanner(onDetect: (capture) { final value = capture.barcodes.first.rawValue; })
  4. For torch, camera switching or stopping and starting, create a MobileScannerController, pass it to the widget, and dispose of it with the screen.
  5. To scan a QR code from a photo, pass the image's file path to the controller's analyzeImage method.

Camera permissions on iOS and Android

  • iOS: every app that uses the camera must set NSCameraUsageDescription. Without it the app crashes when the camera opens.
  • Android: the CAMERA permission is declared in the manifest, which these packages usually add for you, and granted by the user at runtime.
  • Ask at the moment the user taps Scan, with a line explaining why. A cold permission prompt on launch gets refused more often.
  • If the user refuses, explain how to allow it in Settings and offer a way to pick a photo instead.

Generating QR codes and barcodes in the app

For showing a QR code in React Native or Expo, react-native-qrcode-svg is a widely used component; it draws with react-native-svg. In Flutter, qr_flutter draws QR codes, for example QrImageView(data: 'https://example.com', size: 200), and barcode_widget draws Code 128, EAN-13 and other line barcodes.

If you only need a few fixed codes, such as a link on a welcome screen, make them once with a QR code generator and bundle the SVG or PNG as an asset. There is nothing to run on the device and you can style them freely.

Testing your scanner

  • Test on real devices. Simulators and emulators have limited or fake cameras.
  • Try small codes, codes on screens, glossy packaging and low light.
  • Check the scanner types you enabled match what users will scan. Leaving out EAN-13 is a common reason product barcodes are ignored.
  • Keep a set of test codes: a web-based barcode generator and scanner are handy for making and checking samples from your desk.

Read next

FAQ

Questions

What is the best React Native barcode scanner?

react-native-vision-camera with useCodeScanner for custom native builds, or expo-camera's CameraView for Expo apps. Both read QR codes and common barcodes.

Is expo-barcode-scanner still supported?

No. Expo deprecated it in favour of the barcode scanning built into expo-camera and has since removed it from the SDK.

What is the best Flutter QR code scanner package?

mobile_scanner is the most widely used. It reads QR codes and barcodes from the camera and can analyse images from the gallery.

Does an Expo QR code scanner work in Expo Go?

Yes, expo-camera works in Expo Go. react-native-vision-camera needs a development build.

How do I generate a QR code in React Native or Flutter?

Use react-native-qrcode-svg in React Native or Expo, and qr_flutter in Flutter. barcode_widget covers line barcodes in Flutter.