react-native-fabric-barcode-scanner
v2.0.2
Published
High-performance native barcode scanner for React Native with TurboModule + Fabric (New Architecture) support on iOS and Android
Downloads
306
Maintainers
Readme
react-native-fabric-barcode-scanner
High-performance native barcode scanner for React Native — Fabric ScannerView + TurboModule, with AVFoundation (iOS) and CameraX + ML Kit (Android).
npm install react-native-fabric-barcode-scanner
cd ios && pod installNew Architecture recommended. Enable
newArchEnabled=trueon Android. You own the permission UI — the library only normalizes camera status.
Table of contents
- Features
- Why this package?
- Requirements
- Installation
- Quick start
- Basic example
- API
- Supported formats
- Architecture
- Best practices
- Troubleshooting
- FAQ
- Migration
- Contributing
- License
Features
| Feature | Details |
|---------|---------|
| Fabric ScannerView | Continuous barcode scanning as a native view |
| useCameraPermission() | Normalized permission status for your UI |
| TurboModule ScannerModule | Permission + torch control |
| Configurable formats | qr, ean13, code128, and more |
| New Architecture | Codegen Fabric component + TurboModule |
| Old Arch fallback | Android paper sources under android/src/oldarch |
| Android activity-safe | Waits for currentActivity before requesting permission |
Why this package?
Most barcode libraries either wrap a WebView, ship heavy permission UIs you must restyle, or lag behind New Architecture.
| Approach | New Arch (Fabric) | You own permission UI | Native camera stack | |----------|-------------------|------------------------|---------------------| | WebView / JS-only scanners | Varies | Yes | Limited | | UI-heavy scanner kits | Varies | Often no | Yes | | This package | First-class | Yes | AVFoundation / CameraX + ML Kit |
Use it when you want a native preview, format filters, and permission primitives without a baked-in permission screen.
Requirements
| | Minimum |
|--|---------|
| React Native | 0.74.0+ (New Architecture recommended; default on RN 0.76+) |
| React | 18.2+ |
| Node | 18+ (library tooling) |
| iOS | Library fallback 13.4+; host RN floor often 15.1+ (RN 0.76+) via min_ios_version_supported |
| Xcode | ≥ 15.1 (RN 0.74–0.80); ≥ 16.1 (RN 0.81+) |
| Android | API 24+ (Android 7.0) |
| Kotlin (host) | Align with RN template (library fallback 2.1.20) |
| Swift | 5.0 language mode |
| CameraX | 1.6.1 (bundled) |
| ML Kit barcode | 17.3.0 bundled model |
Enable New Architecture (Android):
# android/gradle.properties
newArchEnabled=trueFull upgrade table, ML Kit bundled vs unbundled, and dependency notes: DEPENDENCY_AUDIT.md.
Installation
npm install react-native-fabric-barcode-scanner
# or
yarn add react-native-fabric-barcode-scanner
# or
pnpm add react-native-fabric-barcode-scanneriOS
cd ios && pod installAdd camera usage description to Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera access is required to scan barcodes</string>Android
The library declares camera permission. Ensure it merges into your app (or add explicitly):
<uses-permission android:name="android.permission.CAMERA" />Confirm newArchEnabled=true in android/gradle.properties.
If you link this repo with file:../path and watchFolders, Metro can resolve the library’s nested node_modules/react-native and break TurboModules (PlatformConstants / ScannerModule not found). Force the app’s single copy:
// metro.config.js
const path = require('path');
const localScannerPath = path.resolve(__dirname, '../react-native-custom-scanner');
module.exports = {
// ...
resolver: {
nodeModulesPaths: [path.resolve(__dirname, 'node_modules')],
extraNodeModules: {
'react-native-fabric-barcode-scanner': localScannerPath,
react: path.resolve(__dirname, 'node_modules/react'),
'react-native': path.resolve(__dirname, 'node_modules/react-native'),
},
blockList: [
new RegExp(
`${localScannerPath.replace(/[/\\]/g, '[/\\\\]')}/node_modules/react(/.*)?$`
),
new RegExp(
`${localScannerPath.replace(/[/\\]/g, '[/\\\\]')}/node_modules/react-native(/.*)?$`
),
],
},
};Adjust localScannerPath to your checkout. Rebuild the native app after Metro changes.
Quick start
- Install the package and run
pod install(iOS). - Add
NSCameraUsageDescription/ confirm AndroidCAMERApermission. - Enable New Architecture on Android.
- Request permission with
useCameraPermission(), then mountScannerView.
import { ScannerView, useCameraPermission } from 'react-native-fabric-barcode-scanner';
const { isGranted, isLoading, canRequest, request } = useCameraPermission();
if (isLoading) return null;
if (!isGranted && canRequest) {
return <Button title="Allow camera" onPress={() => { void request(); }} />;
}
if (!isGranted) return null;
return (
<ScannerView
style={{ flex: 1 }}
isActive
scanFormats={['qr', 'ean13']}
onBarcodeScanned={(e) => console.log(e.nativeEvent.value)}
/>
);Basic example
The library normalizes permission status. You build the UI and decide when to call request().
import { Button, Text, View } from 'react-native';
import {
ScannerView,
useCameraPermission,
} from 'react-native-fabric-barcode-scanner';
function ScannerScreen() {
const {
isGranted,
canRequest,
canOpenSettings,
isLoading,
request,
openSettings,
} = useCameraPermission();
if (isLoading) {
return null; // or your spinner
}
if (isGranted) {
return (
<ScannerView
style={{ flex: 1 }}
isActive
scanFormats={['qr', 'ean13', 'code128']}
onBarcodeScanned={(event) => {
const { value, type, timestamp } = event.nativeEvent;
console.log(value, type, timestamp);
}}
/>
);
}
if (canRequest) {
return (
<Button title="Allow camera" onPress={() => { void request(); }} />
);
}
if (canOpenSettings) {
return (
<View>
<Text>Camera access is blocked. Enable it from settings.</Text>
<Button title="Open settings" onPress={openSettings} />
</View>
);
}
return null;
}The hook refreshes automatically when the app returns to the foreground (e.g. after Settings).
API
ScannerView props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| isActive | boolean | true | Start / stop the camera session |
| torchOn | boolean | false | Enable device torch |
| scanFormats | string[] | all supported | Formats to decode |
| onBarcodeScanned | (event) => void | — | Fired while a code is visible |
| style / ViewProps | — | — | Standard React Native view props |
event.nativeEvent:
| Field | Type | Description |
|-------|------|-------------|
| value | string | Decoded payload |
| type | string | Format id (e.g. qr, ean13) |
| timestamp | number | Event timestamp |
onBarcodeScanned={(event) => {
const { value, type, timestamp } = event.nativeEvent;
}}Scans fire continuously while a code stays in frame. Debounce or gate in JS if you need a single accept.
useCameraPermission()
| Field / method | Type | Description |
|----------------|------|-------------|
| status | CameraPermissionStatus | See table below |
| isGranted | boolean | status === 'granted' |
| canRequest | boolean | Show your Allow UI → request() |
| canOpenSettings | boolean | Show your Settings UI → openSettings() |
| isLoading | boolean | True until first check finishes |
| request() | () => Promise<status> | System permission dialog |
| openSettings() | () => void | Opens OS app settings |
| refresh() | () => Promise<state> | Manual re-check |
| Status | Meaning | Typical UI |
|--------|---------|------------|
| granted | Camera allowed | <ScannerView /> |
| not-determined | Never asked | Allow → request() |
| denied | Soft deny (can ask again) | Allow → request() |
| blocked / restricted | Must use Settings | Settings → openSettings() |
Platform mapping (same JS API):
| Scenario | iOS | Android |
|----------|-----|---------|
| Never asked | not-determined | not-determined |
| Allowed | granted | granted |
| Denied, can ask again | — | denied |
| Permanently denied | blocked | blocked |
| Device policy | restricted | — |
Imperative permission API
Prefer the hook. These remain for non-React or legacy code:
| Method | Description |
|--------|-------------|
| getCameraPermissionState() | { status, canRequest, canOpenSettings } |
| requestCameraPermission() | Imperative request |
| openCameraSettings() | Imperative settings |
Torch
| Method | Description |
|--------|-------------|
| ScannerView torchOn | Prefer when the view is mounted |
| setTorchEnabled(enabled) | Toggle torch outside the view |
import { setTorchEnabled } from 'react-native-fabric-barcode-scanner';
setTorchEnabled(true);Exports
import {
ScannerView,
useCameraPermission,
getCameraPermissionState,
requestCameraPermission,
openCameraSettings,
setTorchEnabled,
type BarcodeScannedEvent,
type CameraPermissionStatus,
type CameraPermissionState,
type UseCameraPermissionResult,
} from 'react-native-fabric-barcode-scanner';Supported formats
qr · ean13 · ean8 · upce · code128 · code39 · code93 · pdf417 · aztec · datamatrix · itf14 · interleaved2of5
scanFormats={['qr', 'ean13', 'code128']}Omit scanFormats to allow all supported formats (subject to native decoder support).
Architecture
| Layer | Name |
|-------|------|
| TurboModule | ScannerModule |
| Fabric component | ScannerView |
| Codegen spec | RNCustomScannerSpec |
Native stacks
| Platform | Stack | |----------|--------| | iOS | AVFoundation | | Android | CameraX 1.6.1 + ML Kit barcode 17.3.0 (bundled) |
Legacy architecture: Android paper fallbacks in android/src/oldarch share the same CameraX / ML Kit dependencies — no separate Old-Arch-only Maven artifacts.
Dependency policy & Dependabot: DEPENDENCY_AUDIT.md · .github/dependabot.yml.
Best practices
- Gate the camera — only mount
ScannerViewwhenisGrantedis true. - Own the permission UX — match your brand; the library does not ship screens.
- Debounce scans —
onBarcodeScannedcan fire repeatedly for the same code. - Pause when hidden — set
isActive={false}on blur / modal dismiss to free the camera. - Limit formats — smaller
scanFormatslists can reduce work on busy frames. - Test real devices — simulators / emulators often lack reliable camera + barcode paths.
- New Architecture — keep
newArchEnabled=truealigned with how you develop and ship.
Troubleshooting
ScannerModule / PlatformConstants could not be found
Usually a duplicate React Native when using a local file: link. Apply the Metro extraNodeModules / blockList setup, clear Metro cache, and rebuild the native app.
npx react-native start --reset-cacheCamera permission never appears (Android)
Ensure an Activity is ready before request() (the library waits for currentActivity). Confirm CAMERA is in the merged manifest and New Arch is enabled if you rely on the Fabric path.
iOS crash / missing usage string
Add NSCameraUsageDescription to Info.plist, then clean and rebuild.
Black preview / no scans
- Confirm
isGrantedandisActive={true} - Check
scanFormatsincludes the symbology on the label - Test lighting and focus on a physical device
- Try omitting
scanFormatsonce to rule out filter mismatch
Torch does nothing
Some devices / front cameras lack a torch. Prefer torchOn on ScannerView while mounted; use setTorchEnabled only when appropriate.
Pods / codegen issues after upgrade
cd ios && pod install --repo-update
# Xcode: Product → Clean Build Folder, then rebuildFAQ
Do I need New Architecture?
Strongly recommended. The library is built for Fabric + TurboModules. Android includes old-arch fallbacks, but New Arch is the supported path going forward.
Does this package render a permission screen?
No. Use useCameraPermission() and build your own UI.
Why do I get many onBarcodeScanned events?
Scanning is continuous while a code is visible. Debounce or accept-once in your screen.
Can I use this with Expo?
Use a dev client / prebuild workflow with native modules. It is not a pure Expo Go JS module.
Where is the full dependency upgrade matrix?
See DEPENDENCY_AUDIT.md.
I used old boolean permission helpers — what changed?
See MIGRATION_PERMISSION_API.md.
Migration
Permission API changes (removed boolean helpers → status-based API):
Dependency / ML Kit notes:
Contributing
Issues and PRs: github.com/Rajubarde12/react-native-fabric-barcode-scanner
git clone https://github.com/Rajubarde12/react-native-fabric-barcode-scanner.git
cd react-native-fabric-barcode-scanner
npm install
npm run typecheck
npm run buildPlease open an issue before large native changes. Keep PRs focused and document API changes.
npm whoami
npm run typecheck
npm run build
npm publish --access public
# verify
npm view react-native-fabric-barcode-scanner versionCurrent package version is in package.json (e.g. 2.0.1). Use npm version patch|minor|major for later releases.
License
MIT — see LICENSE.
Links
- npm: react-native-fabric-barcode-scanner
- GitHub: Rajubarde12/react-native-fabric-barcode-scanner
- Issues: Report a bug
Docs wishlist
| Item | Status |
|------|--------|
| Screenshots / GIF of scan flow | Not included yet |
| Before/after permission UI examples | Example code only |
| Performance notes (format filters, frame rate) | Best-practices summary only |
| Expo config plugin | Not shipped |
| Comparison vs vision-camera / other scanners | High-level table above |
