react-qr-code and react-qr-reader serve complementary but fundamentally different purposes in QR code workflows within React applications. react-qr-code is a lightweight, SVG-based component for generating QR codes from strings, optimized for display and styling. react-qr-reader, in contrast, is a browser-based component that uses the device camera to scan and decode QR codes in real time, relying on WebRTC and computer vision libraries under the hood. Neither package handles both generation and scanning — they are specialized tools for opposite ends of the QR interaction spectrum.
At first glance, react-qr-code and react-qr-reader might seem like two sides of the same coin. In practice, they solve entirely different problems with zero overlap in functionality. One draws QR codes; the other reads them from a camera. Confusing them leads to architectural dead ends. Let’s clarify exactly what each does — and how to use them correctly.
react-qr-code generates QR codes as SVG elements.
<svg> you can style, scale, or embed anywhere// react-qr-code: Generate a QR code for a URL
import QRCode from "react-qr-code";
function ShareLink() {
return (
<QRCode
size={256}
value="https://example.com/ticket/12345"
viewBox={`0 0 256 256`}
/>
);
}
react-qr-reader captures and decodes QR codes from the user’s camera.
// react-qr-reader: Scan QR codes from camera
import { useState } from "react";
import { QrReader } from "react-qr-reader";
function Scanner() {
const [data, setData] = useState("No result");
return (
<>
<QrReader
onResult={(result, error) => {
if (!!result) setData(result?.text);
if (!!error) console.info(error);
}}
constraints={{ facingMode: "environment" }}
containerStyle={{ width: "100%" }}
/>
<p>{data}</p>
</>
);
}
⚠️ Critical distinction: You cannot use
react-qr-codeto scan anything, andreact-qr-readercannot render a QR image. They are mutually exclusive in function.
react-qr-code gives you full SVG control.
fgColor/bgColormargin<QRCode
value="Custom styled QR"
fgColor="#000080" // Dark blue modules
bgColor="#F0F8FF" // Alice blue background
margin={4} // Quiet zone padding
/>
react-qr-reader offers limited visual customization.
containerStyle<QrReader
containerStyle={{
position: "relative",
width: "300px",
height: "300px",
border: "2px solid #007bff"
}}
videoStyle={{
objectFit: "cover"
}}
/>
// Add overlay separately:
<div style={{
position: "absolute",
top: "50px",
left: "50px",
width: "200px",
height: "200px",
border: "2px dashed red"
}} />
react-qr-code works everywhere.
react-qr-reader requires specific conditions:
facingMode: "environment")Always handle errors gracefully:
<QrReader
onResult={(result, error) => {
if (error?.name === "NotAllowedError") {
alert("Camera access denied. Please enable permissions.");
}
}}
/>
react-qr-code is dependency-free.
react-qr-reader bundles heavy decoding libraries.
@zxing/library for QR parsingThis affects your app’s startup time — avoid loading react-qr-reader until the scan feature is needed (code-splitting recommended):
// Lazy-load scanner only when required
const Scanner = lazy(() => import("./Scanner"));
function App() {
const [showScanner, setShowScanner] = useState(false);
return (
<>
<button onClick={() => setShowScanner(true)}>
Open Scanner
</button>
{showScanner && <Scanner />}
</>
);
}
You’ll need both packages:
// Ticket generator (admin side)
<QRCode value={`event:conf2024:user:${userId}`} />
// Ticket scanner (staff side)
<QrReader
onResult={(result) => {
if (result?.text.startsWith("event:conf2024:")) {
validateTicket(result.text);
}
}}
/>
Update react-qr-code’s value prop to change content:
function DynamicQR() {
const [input, setInput] = useState("");
return (
<>
<input value={input} onChange={e => setInput(e.target.value)} />
<QRCode value={input || "Enter text"} />
</>
);
}
Use react-qr-reader to trigger actions:
<QrReader
onResult={(result) => {
if (result?.text.startsWith("https://")) {
window.open(result.text, "_blank");
}
}}
/>
react-qr-reader works on HTTP: It won’t. Use localhost for dev, but deploy to HTTPS.react-qr-code with CSS filters: Stick to fgColor/bgColor. CSS transforms may break QR readability.constraints={{ facingMode: "environment" }} for rear camera on phones.| Scenario | Package to Use |
|---|---|
| Show a QR code for payment | react-qr-code |
| Scan a QR code from user’s camera | react-qr-reader |
| Print QR codes on documents | react-qr-code |
| Authenticate via QR token | react-qr-reader |
| Embed QR in email templates | ❌ Neither (use server-side generation) |
Treat these as specialized single-purpose tools:
react-qr-codereact-qr-readerNever try to force one into the other’s role. If your app requires both capabilities (common in ticketing, payments, or IoT), install both packages — they coexist peacefully and cover the full QR workflow spectrum.
Choose react-qr-code when you need to display QR codes in your UI — for example, showing a payment link, sharing a WiFi password, or rendering a ticket identifier. It’s ideal for static or dynamic QR rendering with full control over visual appearance via standard SVG props. Avoid it if you need scanning capabilities; this package only generates codes.
Choose react-qr-reader when your application must read QR codes from a live camera feed, such as scanning boarding passes, authenticating users via QR tokens, or processing inventory tags. It handles camera access, video streaming, and decoding automatically. Do not use it for generating QR images — it has no rendering functionality.
A
npm i react-qr-code
When using this library with React Native, you will also need to have react-native-svg installed.
npm i react-native-svg
cd ios && pod install
import React from "react";
import ReactDOM from "react-dom";
import QRCode from "react-qr-code";
ReactDOM.render(<QRCode value="hey" />, document.getElementById("Container"));
Note: If the QR code is likely to appear next to dark objects, you will need to wrap it in a light-colored container to preserve the 'quiet zone', e.g.
<div style={{ background: 'white', padding: '16px' }}>
<QRCode ... />
</div>
Responsive QR code example:
// Can be anything instead of `maxWidth` that limits the width.
<div style={{ height: "auto", margin: "0 auto", maxWidth: 64, width: "100%" }}>
<QRCode
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
value={value}
viewBox={`0 0 256 256`}
/>
</div>
| prop | type | default value | platform |
|---|---|---|---|
bgColor | string | '#FFFFFF' | web, ios, android |
fgColor | string | '#000000' | web, ios, android |
level | string ('L' 'M' 'Q' 'H') | 'L' | web, ios, android |
size | number | 256 | web, ios, android |
title | string | web | |
value | string | web, ios, android |
Adheres to the official QR spec and can store up to 2953 characters in value.
MIT