An open API service indexing awesome lists of open source software.

https://github.com/yudielcurbelo/react-qr-scanner

A library to scan QR Codes in react.
https://github.com/yudielcurbelo/react-qr-scanner

qr qr-code qrcode-reader qrcode-scanner react reactjs reader scanner typescript

Last synced: 7 months ago
JSON representation

A library to scan QR Codes in react.

Awesome Lists containing this project

README

          

# @yudiel/react-qr-scanner

[![npm version](https://img.shields.io/npm/v/@yudiel/react-qr-scanner.svg)](https://www.npmjs.com/package/@yudiel/react-qr-scanner)
[![npm downloads](https://img.shields.io/npm/dm/@yudiel/react-qr-scanner.svg)](https://www.npmjs.com/package/@yudiel/react-qr-scanner)
[![license](https://img.shields.io/npm/l/@yudiel/react-qr-scanner.svg)](https://github.com/yudielcurbelo/react-qr-scanner/blob/main/LICENSE)

A modern React library for scanning QR codes and barcodes using your device camera or webcam. Built on top of the Barcode Detection API with React hooks and components.

## Features

- **Multiple Barcode Formats** - Supports QR codes, EAN, UPC, Code 128, and many more 1D/2D formats
- **Camera Controls** - Built-in torch (flashlight), zoom, and camera switching capabilities
- **Flexible Scanning** - Continuous scanning, single scan mode, or pause/resume functionality
- **Custom Tracking** - Draw custom overlays and tracking visualizations on detected barcodes
- **Device Selection** - Choose specific cameras with the `useDevices` hook
- **Customizable UI** - Custom styles, class names, and component overrides
- **Audio Feedback** - Optional beep sound on successful scans (with custom sound support)
- **TypeScript Support** - Fully typed for excellent developer experience
- **Lightweight** - Minimal dependencies with optimized bundle size
- **Cross-browser Compatible** - Works across modern browsers with `webrtc-adapter`

## Table of Contents

- [Demo](#demo)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Usage Examples](#usage-examples)
- [Basic Scanner](#basic-scanner)
- [Device Selection](#device-selection)
- [Camera Constraints](#camera-constraints)
- [Custom Tracking Overlay](#custom-tracking-overlay)
- [Pausing and Resuming](#pausing-and-resuming)
- [UI Components](#ui-components)
- [API Reference](#api-reference)
- [Scanner Props](#scanner-props)
- [useDevices Hook](#usedevices-hook)
- [Supported Formats](#supported-formats)
- [Type Definitions](#type-definitions)
- [Browser Support](#browser-support)
- [Limitations](#limitations)
- [Contributing](#contributing)
- [License](#license)

## Demo

Check out the [live demo](https://yudielcurbelo.github.io/react-qr-scanner/) to see the scanner in action.

## Installation

```bash
npm install @yudiel/react-qr-scanner
```

```bash
yarn add @yudiel/react-qr-scanner
```

```bash
pnpm add @yudiel/react-qr-scanner
```

## Quick Start

```jsx
import { Scanner } from '@yudiel/react-qr-scanner';

function App() {
return (
console.log(result)}
onError={(error) => console.log(error?.message)}
/>
);
}
```

## Usage Examples

### Basic Scanner

```jsx
import { Scanner } from '@yudiel/react-qr-scanner';

function BasicExample() {
const handleScan = (detectedCodes) => {
console.log('Detected codes:', detectedCodes);
// detectedCodes is an array of IDetectedBarcode objects
detectedCodes.forEach(code => {
console.log(`Format: ${code.format}, Value: ${code.rawValue}`);
});
};

return (
console.error(error)}
/>
);
}
```

### Device Selection

Use the `useDevices` hook to list available cameras and select a specific device:

```jsx
import { Scanner, useDevices } from '@yudiel/react-qr-scanner';
import { useState } from 'react';

function DeviceSelectionExample() {
const devices = useDevices();
const [selectedDevice, setSelectedDevice] = useState(null);

return (


setSelectedDevice(e.target.value)}>
Select a camera
{devices.map((device) => (

{device.label || `Camera ${device.deviceId}`}

))}

console.log(result)}
constraints={{
deviceId: selectedDevice,
}}
/>


);
}
```

### Camera Constraints

Customize camera settings using MediaTrackConstraints:

```jsx
import { Scanner } from '@yudiel/react-qr-scanner';

function ConstraintsExample() {
return (
console.log(result)}
constraints={{
facingMode: 'environment', // Use rear camera
aspectRatio: 1, // Square aspect ratio
// Advanced constraints
width: { ideal: 1920 },
height: { ideal: 1080 },
}}
/>
);
}
```

### Custom Tracking Overlay

Draw custom visualizations on detected barcodes:

```jsx
import { Scanner } from '@yudiel/react-qr-scanner';

function TrackingExample() {
const highlightCodeOnCanvas = (detectedCodes, ctx) => {
detectedCodes.forEach((detectedCode) => {
const { boundingBox, cornerPoints } = detectedCode;

// Draw bounding box
ctx.strokeStyle = '#00FF00';
ctx.lineWidth = 4;
ctx.strokeRect(
boundingBox.x,
boundingBox.y,
boundingBox.width,
boundingBox.height
);

// Draw corner points
ctx.fillStyle = '#FF0000';
cornerPoints.forEach((point) => {
ctx.beginPath();
ctx.arc(point.x, point.y, 5, 0, 2 * Math.PI);
ctx.fill();
});
});
};

return (
console.log(result)}
components={{
tracker: highlightCodeOnCanvas,
}}
/>
);
}
```

### Pausing and Resuming

Control when the scanner is active:

```jsx
import { Scanner } from '@yudiel/react-qr-scanner';
import { useState } from 'react';

function PauseExample() {
const [isPaused, setIsPaused] = useState(false);

return (


setIsPaused(!isPaused)}>
{isPaused ? 'Resume' : 'Pause'} Scanning

console.log(result)}
paused={isPaused}
/>


);
}
```

### UI Components

Enable built-in UI controls for torch, zoom, and camera switching:

```jsx
import { Scanner } from '@yudiel/react-qr-scanner';

function UIComponentsExample() {
return (
console.log(result)}
components={{
audio: true, // Play beep sound on scan
onOff: true, // Show camera on/off button
torch: true, // Show torch/flashlight button (if supported)
zoom: true, // Show zoom control (if supported)
finder: true, // Show finder overlay
}}
// Custom sound (base64 encoded audio)
sound="data:audio/mp3;base64,YOUR_BASE64_AUDIO_HERE"
/>
);
}
```

## API Reference

### Scanner Props

| Prop | Type | Required | Default | Description |
|-----------------|-----------------------------------------------|----------|---------|--------------------------------------------------------------------------------------------------|
| `onScan` | `(detectedCodes: IDetectedBarcode[]) => void` | Yes | - | Callback function called when one or more barcodes are detected. |
| `onError` | `(error: unknown) => void` | No | - | Callback function called when an error occurs while accessing the camera. |
| `constraints` | `MediaTrackConstraints` | No | `{}` | Media track constraints to apply to the video stream (e.g., `facingMode`, `deviceId`). |
| `formats` | `BarcodeFormat[]` | No | All | Array of barcode formats to detect. If not specified, all supported formats are detected. |
| `paused` | `boolean` | No | `false` | If `true`, the scanner pauses and displays the last frame. |
| `children` | `ReactNode` | No | - | Custom children to render inside the scanner container. |
| `components` | `IScannerComponents` | No | `{}` | Configuration for built-in UI components and custom tracker function. |
| `styles` | `IScannerStyles` | No | `{}` | Custom CSS styles for scanner elements. |
| `classNames` | `IScannerClassNames` | No | `{}` | Custom CSS class names for scanner elements. |
| `scanDelay` | `number` | No | `500` | Delay in milliseconds between successful scans. Prevents duplicate detections. |
| `allowMultiple` | `boolean` | No | `false` | If `true`, allows the same barcode to trigger `onScan` multiple times. |
| `sound` | `boolean \| string` | No | `false` | If `true`, plays default beep sound. Provide a base64 audio string for custom sound. |

### useDevices Hook

Returns an array of available video input devices (cameras).

```typescript
const devices = useDevices();
// Returns: MediaDeviceInfo[]
```

**Example:**

```jsx
import { useDevices } from '@yudiel/react-qr-scanner';

function CameraList() {
const devices = useDevices();

return (


    {devices.map((device) => (

  • {device.label || `Camera ${device.deviceId}`}

  • ))}

);
}
```

## Supported Formats

The library supports detection of the following barcode formats:

| 1D Barcodes | 2D Barcodes |
|------------------|---------------|
| Codabar | Aztec |
| Code 39 | Data Matrix |
| Code 93 | Matrix Codes |
| Code 128 | Maxi Code |
| Databar | Micro QR Code |
| Databar Expanded | PDF 417 |
| Dx Film Edge | QR Code |
| EAN 8 | rMQR Code |
| EAN 13 | |
| ITF | |
| Linear Codes | |
| UPC A | |
| UPC E | |

To detect specific formats only:

```jsx
console.log(result)}
formats={['qr_code', 'ean_13', 'code_128']}
/>
```

## Type Definitions

### `BarcodeFormat`

```typescript
type BarcodeFormat =
| 'aztec'
| 'code_128'
| 'code_39'
| 'code_93'
| 'codabar'
| 'databar'
| 'databar_expanded'
| 'data_matrix'
| 'dx_film_edge'
| 'ean_13'
| 'ean_8'
| 'itf'
| 'maxi_code'
| 'micro_qr_code'
| 'pdf417'
| 'qr_code'
| 'rm_qr_code'
| 'upc_a'
| 'upc_e'
| 'linear_codes'
| 'matrix_codes'
| 'unknown';
```

### `IDetectedBarcode`

```typescript
interface IDetectedBarcode {
boundingBox: IBoundingBox;
cornerPoints: IPoint[];
format: string;
rawValue: string;
}
```

### `IBoundingBox`

```typescript
interface IBoundingBox {
x: number;
y: number;
width: number;
height: number;
}
```

### `IPoint`

```typescript
interface IPoint {
x: number;
y: number;
}
```

### `IScannerComponents`

```typescript
interface IScannerComponents {
tracker?: TrackFunction;
onOff?: boolean;
torch?: boolean;
zoom?: boolean;
finder?: boolean;
}
```

### `TrackFunction`

```typescript
type TrackFunction = (
detectedCodes: IDetectedBarcode[],
ctx: CanvasRenderingContext2D
) => void;
```

### `IScannerStyles`

```typescript
interface IScannerStyles {
container?: CSSProperties;
video?: CSSProperties;
finderBorder?: number;
}
```

### `IScannerClassNames`

```typescript
interface IScannerClassNames {
container?: string;
video?: string;
}
```

## Browser Support

This library requires support for:
- **getUserMedia API** - Camera access
- **Barcode Detection API** - Barcode scanning (polyfilled via [barcode-detector](https://www.npmjs.com/package/barcode-detector))
- **Canvas API** - Drawing tracking overlays

**Supported Browsers:**
- Chrome/Edge 88+
- Firefox 90+ (with polyfill)
- Safari 14+ (with polyfill)
- Mobile browsers (iOS Safari 14.5+, Chrome Mobile)

The library uses `webrtc-adapter` for cross-browser compatibility.

## Limitations

- **HTTPS or localhost required** - Due to browser security restrictions, camera access only works on secure contexts (HTTPS or localhost).
- **iOS audio limitations** - Beep sound on iOS Safari requires user interaction before playing. The first scan after page load may not play sound.
- **Server-Side Rendering (SSR)** - This library requires browser APIs and will not work during SSR. Ensure you only import and use it in client-side code:

```jsx
// Next.js example
import dynamic from 'next/dynamic';

const Scanner = dynamic(
() => import('@yudiel/react-qr-scanner').then((mod) => mod.Scanner),
{ ssr: false }
);
```

- **Mobile browser constraints** - Some mobile browsers cannot use torch and zoom simultaneously. The library automatically disables torch when zoom is activated to prevent conflicts.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

[MIT](https://github.com/yudielcurbelo/react-qr-scanner/blob/main/LICENSE) © [Yudiel Curbelo](https://github.com/yudielcurbelo)