Fix banquet mode ignored on web: use latest onScan in camera loop

The web scanner's camera loop starts once in useEffect and closed over the
mount-time onScan handler, so switching modes (e.g. to Banquet) kept invoking
the original ticket-check-in handler. Route onScan through a ref updated each
render so the loop always calls the current handler. Native was unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hank 2026-07-08 16:31:25 +00:00
parent 3583c2e15f
commit 336d2a5c83

View file

@ -10,11 +10,16 @@ export default function QRScanner({ onScan, active }: QRScannerProps) {
const streamRef = useRef<MediaStream | null>(null);
const rafRef = useRef<number | null>(null);
const activeRef = useRef(active);
// Route onScan through a ref so the long-lived camera loop (started once in
// useEffect) always calls the LATEST handler — otherwise a mode switch
// (e.g. to Banquet) keeps hitting the mount-time handler.
const onScanRef = useRef(onScan);
const lastScan = useRef<{ code: string; at: number }>({ code: "", at: 0 });
const [error, setError] = useState<string | null>(null);
const [starting, setStarting] = useState(true);
activeRef.current = active;
onScanRef.current = onScan;
async function start() {
setError(null);
@ -45,7 +50,7 @@ export default function QRScanner({ onScan, active }: QRScannerProps) {
const now = Date.now();
if (!(data === lastScan.current.code && now - lastScan.current.at < 3000)) {
lastScan.current = { code: data, at: now };
onScan(data);
onScanRef.current(data);
}
}
} catch {