Working with Barcode and QR Codes
1. Scanning Barcodes
| Property | Description | Values |
|---|---|---|
| barCodeTypes | Array of barcode types to scan | ['ean13', 'ean8', 'upc', 'upce', 'code39', 'code128', 'codabar', 'i2of5', 'itf14', 'qr', 'pdf417', 'aztec'] |
| onBarCodeScanned | Callback function when a barcode is scanned | Function with { data, type } parameter |
| flashMode | Flashlight mode for scanning | 'auto', 'on', 'off', 'torch' |
Example: Basic Barcode Scanner
import { BarCodeScanner } from 'expo-barcode-scanner';
import { useState, useEffect } from 'react';
export default function BarcodeScanner() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ data, type }) => {
setScanned(true);
alert(`Scanned ${type}: ${data}`);
};
if (hasPermission === null) {
return <View style={{ flex: 1 }}><Text>Requesting camera permission</Text></View>;
}
if (hasPermission === false) {
return <View style={{ flex: 1 }}><Text>No access to camera</Text></View>;
}
return (
<View style={{ flex: 1 }}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
barCodeTypes={[BarCodeScanner.Constants.BarCodeType.qr]}
style={{ flex: 1 }}
/>
</View>
);
}
Note: Ensure camera permissions are requested before using the scanner.
Warning: The scanner stops scanning once a code is detected unless
scanned is reset.
2. Configuring Barcode Types
| Barcode Type | Description | Supported in Expo | Notes |
|---|---|---|---|
| CODE_128 | 128-character alphanumeric barcode | NEW | Most commonly used for inventory management |
| CODE_39 | 39-character alphanumeric barcode | Yes | Used in retail and manufacturing |
| EAN_13 | 13-digit European Article Number | Yes | Standard for retail products |
| EAN_8 | 8-digit European Article Number | Yes | Shorter version of EAN-13 |
| UPC_A | 12-digit Universal Product Code | Yes | Common in North America |
| QR_CODE | 2D QR code with variable data capacity | NEW | Used for web links, contact info, etc. |
Example: Scanning QR Code
import { BarCodeScanner } from 'expo-barcode-scanner';
const scanQRCode = async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
if (status === 'granted') {
const result = await BarCodeScanner.scanFromCameraAsync({
barCodeTypes: [BarCodeScanner.Constants.BarCodeType.qr]
});
console.log('Scanned:', result.data);
}
};
3. Using expo-barcode-scanner
| Property | Description | Default | Notes |
|---|---|---|---|
| barCodeTypes | Array of barcode types to scan for | ['qr', 'ean13', 'ean8', 'upce', 'code128', 'code39', 'codabar', 'i25', 'itf14', 'pdf417'] |
Supports multiple barcode types |
| onBarCodeScanned | Callback function when a barcode is scanned | null |
Receives { data, type } object |
| flashMode | Flashlight mode for scanning | 'auto' |
Options: 'off', 'on', 'auto', 'torch' |
Example: Scanning QR Codes
import { BarCodeScanner } from 'expo-barcode-scanner';
import { useState, useEffect } from 'react';
export default function QRScanner() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ data }) => {
setScanned(true);
alert(`Scanned: ${data}`);
};
if (hasPermission === null) {
return <View><Text>Requesting camera permission</Text></View>;
}
if (hasPermission === false) {
return <View><Text>No access to camera</Text></View>;
}
return (
<View style={{ flex: 1, flexDirection: 'column' }}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
barCodeTypes={[BarCodeScanner.Constants.BarCodeType.qr]}
style={{ flex: 1, width: '100%' }}
/>
</View>
);
}
Note: Ensure camera permissions are requested before using the scanner.
Warning: The scanner will stop scanning once a barcode is detected unless you set
scanned to false.
4. Handling Scanned Data
| Property | Description | Example |
|---|---|---|
| data | The scanned data as a string | "https://expo.dev" |
| type | Type of the scanned code (e.g., QR_CODE, AZTEC) | "QR_CODE" |
| bounds | Bounds of the scanned code in the image | { origin: { x: 10, y: 20 }, size: { width: 100, height: 100 } } |
Example: Processing Scanned Data
import { BarCodeScanner } from 'expo-barcode-scanner';
const handleBarCodeScanned = ({ data, type }) => {
console.log(`Scanned ${type}:`, data);
if (type === 'QR_CODE') {
// Handle QR code
console.log('QR Code data:', data);
} else if (type === 'EAN_13') {
// Handle EAN-13 barcode
console.log('EAN-13 data:', data);
}
};
Note: The
data property contains the actual scanned content, which could be a URL, text, or other data depending on the barcode type.
5. Generating QR Codes
| Property | Description | Example |
|---|---|---|
| value | The data to encode into the QR code | "https://expo.dev" |
| size | Size of the QR code in pixels | 200 |
| backgroundColor | Background color of the QR code | "#ffffff" |
| foregroundColor | Color of the QR code modules | "#000000" |
Example: Basic QR Code Generation
import { BarCodeScanner } from 'expo-barcode-scanner';\n\nconst qrCodeData = "https://expo.dev";\nconst size = 200;\n\n// Generate QR code with default settings\n<BarCodeScanner\n value={qrCodeData}\n format="QR_CODE"\n size={size}\n backgroundColor="#ffffff"\n foregroundColor="#000000"\n/>
Example: Custom Styled QR Code
import { BarCodeScanner } from 'expo-barcode-scanner';\n\nconst qrCodeData = "https://expo.dev";\nconst size = 300;\n\n// Generate QR code with custom colors and size\n<BarCodeScanner\n value={qrCodeData}\n format="QR_CODE"\n size={size}\n backgroundColor="#f0f0f0"\n foregroundColor="#333333"\n/>
6. Customizing QR Appearance
| Property | Values | Description |
|---|---|---|
| backgroundColor | "#ffffff" |
Background color of the QR code |
| foregroundColor | "#000000" |
Color of the QR code modules |
| size | 200 |
Size of the QR code in pixels |
| margin | 1 |
Margin around the QR code in modules |
Example: Customizing QR Code Appearance
import { BarCodeScanner } from 'expo-barcode-scanner';
<BarCodeScanner
onBarCodeScanned={handleBarCodeScanned}
backgroundColor="#ffffff"
foregroundColor="#000000"
size={250}
margin={2}
/>
7. Embedding Logos in QR
| Property | Description | Values |
|---|---|---|
| logo | Image to embed in the center of the QR code | string (URI or base64 encoded image) |
| logoSize | Size of the logo in pixels | number |
| logoBackgroundColor | Background color behind the logo | string (hex or CSS color) |
Example: Embedding a Logo in QR Code
import { BarCodeScanner } from 'expo-barcode-scanner';
const qrData = {
logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==',
logoSize: 40,
logoBackgroundColor: '#ffffff'
};
// Generate QR code with embedded logo
const qrCode = await BarCodeScanner.generate({
...qrData,
value: 'https://expo.dev',
format: 'QR_CODE'
});
Note: The logo must be a square image and should not exceed 20% of the QR code size to maintain scannability.
8. Scanning Multiple Barcodes
Example: Scanning Multiple Barcodes
import { BarCodeScanner } from 'expo-barcode-scanner';
import { useState } from 'react';
export default function MultiBarcodeScanner() {
const [scannedBarcodes, setScannedBarcodes] = useState([]);
const handleBarCodeScanned = ({ data, type }) => {
setScannedBarcodes(prev => [...prev, { data, type }]);
};
return (
<BarCodeScanner
onBarCodeScanned={handleBarCodeScanned}
style={{ flex: 1 }}
/>
);
}
| Property | Description | Notes |
|---|---|---|
| onBarCodeScanned | Callback function when a barcode is scanned | Receives an object with data and type |
| scannedBarcodes | Array of scanned barcode data | Each item is an object with data and type |
Note: The scanner will continue to detect barcodes until the component is unmounted or
onBarCodeScanned is set to null.
9. Using Barcode Overlay
Example: Scanning Barcode with Overlay
import { BarCodeScanner } from 'expo-barcode-scanner';
import { View, StyleSheet } from 'react-native';
export default function BarcodeScanner() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ data }) => {
setScanned(true);
alert(`Scanned: ${data}`);
};
if (hasPermission === null) {
return <View style={styles.container}><Text>Requesting camera permission</Text></View>;
}
if (hasPermission === false) {
return <View style={styles.container}><Text>No access to camera</Text></View>;
}
return (
<View style={styles.container}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
formats={[BarCodeScanner.Constants.BarCodeType.code128]}
/>
<View style={styles.overlay}>
<View style={styles.scanArea}></View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
},
overlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'center',
alignItems: 'center',
},
scanArea: {
width: 200,
height: 200,
borderWidth: 2,
borderColor: '#fff',
borderRadius: 10,
},
});
| Property | Description | Values |
|---|---|---|
| formats | Barcode types to scan | [BarCodeScanner.Constants.BarCodeType.code128] |
| onBarCodeScanned | Callback when a barcode is scanned | Function that receives { data } |
| style | Styling for the scanner view | StyleSheet.absoluteFillObject |
Note: The overlay is a visual guide to help users align the barcode within the scan area.
10. Handling Invalid Scans
Example: Basic Scan Error Handling
import { BarCodeScanner } from 'expo-barcode-scanner';
const handleScan = (data, type) => {
if (!data) {
console.warn("Scan failed or cancelled");
return;
}
try {
const parsedData = JSON.parse(data);
console.log("Scanned data:", parsedData);
} catch (error) {
console.error("Invalid scan data format", error);
}
};
const handleBarCodeScanned = ({ data, type }) => {
if (type === BarCodeScanner.Constants.BarCodeType.qr) {
handleScan(data, type);
} else {
console.warn("Unsupported barcode type", type);
}
};
| Property | Description | Notes |
|---|---|---|
| data | Scanned data string | May be null or empty for invalid scans |
| type | Barcode type identifier | Use BarCodeScanner.Constants.BarCodeType |
| cancelled | Boolean indicating if scan was cancelled | Set to true when user cancels scan |
Note: Always validate scanned data before processing to prevent runtime errors from malformed input.
Warning: Never assume all scanned data is valid JSON or parseable content. Always wrap parsing logic in try/catch blocks.
Best Practices for Invalid Scan Handling
- Check for null or empty
datavalues - Validate barcode type before processing
- Wrap data parsing in try/catch blocks
- Provide user feedback for failed scans
- Log invalid scan attempts for debugging
11. Setting Scan Area
| Property | Description | Default | Notes |
|---|---|---|---|
| scanArea | Defines the rectangular area within the camera view where barcodes can be detected. It's an object with x, y, width, and height properties, all in normalized coordinates (0 to 1). |
{ x: 0, y: 0, width: 1, height: 1 } |
Only the area defined by this rectangle will be scanned for barcodes. Useful to focus scanning on specific regions of the camera feed. |
Example: Define a Custom Scan Area
import { BarCodeScanner } from 'expo-barcode-scanner';
const scanArea = {
x: 0.25,
y: 0.25,
width: 0.5,
height: 0.5
};
// Use in BarCodeScanner
<BarCodeScanner
onBarCodeScanned={handleBarCodeScanned}
scanArea={scanArea}
/>
12. Using Torch for Scanning
| Property | Description | Values |
|---|---|---|
| torch | Enables or disables torch (flashlight) for scanning | true / false |
| torchMode | Controls torch behavior | "on", "off", "auto" |
Example: Enable Torch for Scanning
import { BarCodeScanner } from 'expo-barcode-scanner';
const App = () => {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ data }) => {
setScanned(true);
alert(`Scanned: ${data}`);
};
if (hasPermission === null) {
return <View style={styles.container}><Text>Requesting camera permission</Text></View>;
}
if (hasPermission === false) {
return <View style={styles.container}><Text>No access to camera</Text></View>;
}
return (
<View style={styles.container}>
<BarCodeScanner
onBarCodeScanned={handleBarCodeScanned}
torchMode="on"
style={StyleSheet.absoluteFillObject}
/>
</View>
);
};
Note: The torch mode only works on devices that support flashlight functionality.
Warning: Enabling torch may drain battery faster. Use it only when necessary.