Building a Web NFC React Hook
Introduction
Managing Web NFC state (scanning, writing, errors, support) directly in your components can lead to messy code. Creating a custom React hook allows you to encapsulate this logic and reuse it across your application.
The useNfc Hook
Here is a simple implementation of a useNfc hook that handles reading tags.
import { useState, useEffect, useCallback } from 'react';
export function useNfc() {
const [isSupported, setIsSupported] = useState(false);
const [isScanning, setIsScanning] = useState(false);
const [message, setMessage] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
if ('NDEFReader' in window) {
setIsSupported(true);
}
}, []);
const scan = useCallback(async () => {
if (!isSupported) return;
try {
const ndef = new window.NDEFReader();
await ndef.scan();
setIsScanning(true);
setError(null);
ndef.onreading = (event) => {
setMessage(event.message);
};
ndef.onreadingerror = () => {
setError('Error reading tag.');
};
} catch (err) {
setError(err.message);
setIsScanning(false);
}
}, [isSupported]);
return { isSupported, isScanning, message, error, scan };
}Usage
You can now use this hook in any component:
export default function NfcReader() {
const { isSupported, isScanning, message, scan, error } = useNfc();
if (!isSupported) {
return <p>Web NFC is not supported.</p>;
}
return (
<div>
<button onClick={scan} disabled={isScanning}>
{isScanning ? 'Scanning...' : 'Start Scan'}
</button>
{error && <p>Error: {error}</p>}
{message && <p>Tag detected!</p>}
</div>
);
}