In this tutorial, you'll build a production-ready QR code generator component for React. We'll use React hooks for state management and the QR Code API for generation.
What You'll Build
- A reusable
<QRCode />component - A custom
useQRCodehook for API calls - Loading states and error handling
- Download functionality
Basic QR Code Component
Let's start with a simple component that generates and displays a QR code:
QRCode.jsx
import { useState, useEffect } from 'react';
export function QRCode({ data, size = 200 }) {
const [qrUrl, setQrUrl] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const generateQR = async () => {
try {
setLoading(true);
const response = await fetch('https://www.qrcodeapi.io/api/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.REACT_APP_QR_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ data, size, format: 'png' })
});
if (!response.ok) throw new Error('Failed to generate QR code');
const blob = await response.blob();
setQrUrl(URL.createObjectURL(blob));
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
if (data) generateQR();
}, [data, size]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return <img src={qrUrl} alt="QR Code" width={size} height={size} />;
}
Custom Hook: useQRCode
For better reusability, let's extract the logic into a custom hook:
useQRCode.js
import { useState, useEffect, useCallback } from 'react';
export function useQRCode(data, options = {}) {
const {
size = 200,
format = 'png',
color = '#000000',
background = '#ffffff'
} = options;
const [qrUrl, setQrUrl] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const generate = useCallback(async () => {
if (!data) return;
setLoading(true);
setError(null);
try {
const response = await fetch('https://www.qrcodeapi.io/api/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.REACT_APP_QR_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ data, size, format, color, background })
});
if (!response.ok) {
const err = await response.json();
throw new Error(err.message || 'Generation failed');
}
const blob = await response.blob();
// Clean up previous URL
if (qrUrl) URL.revokeObjectURL(qrUrl);
setQrUrl(URL.createObjectURL(blob));
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}, [data, size, format, color, background]);
useEffect(() => {
generate();
}, [generate]);
return { qrUrl, loading, error, regenerate: generate };
}
Complete Component with Download
Here's a full-featured component with download functionality:
QRCodeGenerator.jsx
import { useState } from 'react';
import { useQRCode } from './useQRCode';
export function QRCodeGenerator() {
const [input, setInput] = useState('');
const [data, setData] = useState('');
const { qrUrl, loading, error } = useQRCode(data, { size: 300 });
const handleGenerate = () => setData(input);
const handleDownload = () => {
if (!qrUrl) return;
const link = document.createElement('a');
link.href = qrUrl;
link.download = 'qrcode.png';
link.click();
};
return (
<div className="qr-generator">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Enter URL or text"
/>
<button onClick={handleGenerate} disabled={!input || loading}>
{loading ? 'Generating...' : 'Generate QR Code'}
</button>
{error && <p className="error">{error}</p>}
{qrUrl && (
<div className="qr-result">
<img src={qrUrl} alt="QR Code" />
<button onClick={handleDownload}>Download</button>
</div>
)}
</div>
);
}
Environment Setup
Store your API key safely in environment variables:
.env
REACT_APP_QR_API_KEY=your_api_key_here
Best Practices
- Never expose API keys in client-side code for production - Use a backend proxy
- Clean up object URLs with
URL.revokeObjectURL()to prevent memory leaks - Debounce input changes if generating on type
- Show loading states for better UX
- Cache generated QR codes when possible
Ready to Build Your React QR Generator?
Get your free API key and start building today.
Get Your Free API Key