Camera-Based Barcode Scanning (Frontend)
Food Tracker (FastAPI)
Chapter 4 · Camera-Based Barcode Scanning (Frontend)
This is the one chapter in this entire course with no FastAPI involvement at all — the same is true of every sibling course's own Chapter 4. What's genuinely different here is the frontend it's written against: plain JavaScript, no React, no hooks, no component lifecycle to lean on.
Requesting Camera Access
facingMode: "environment" requests the rear camera — the same call every sibling course's own scanning chapter starts with, since decoding a barcode client-side has nothing to do with which framework, or lack of one, sits around it.
Decoding, Written as Plain Functions
The same BarcodeDetector-with-ZXing-fallback logic every sibling course uses, here with no useEffect, no useRef — just a module-level variable holding the active stream, and two exported functions:
Wiring It Into the App's Views
This app has no client-side router — Chapter 1's static-file setup serves one index.html, and separate "views" are plain <div> sections shown and hidden with a CSS class, toggled by JavaScript:
useEffect's own return function runs whenever the component unmounts, with no way to forget it once it's written. Vanilla JS has no equivalent lifecycle concept at all: there's no "unmount" event when a plain <div> gets hidden by a CSS class. stopScanner() has to be called explicitly, by name, at every single place a user could leave the scan view — a successful scan, a cancel button, even a back-button handler if one existed. Miss even one path and the camera silently keeps running, with nothing in the language or the DOM to catch the mistake. This is the honest, direct cost of Chapter 1's own "deliberately minimal, no framework" choice: fewer moving parts, but every lifecycle guarantee React provides for free here becomes the developer's own manual responsibility instead.
stopScanner() in two places — once inside onDetected, once in the cancel button's handler — specifically because there are two distinct ways to leave the scan view. Adding a third way to leave later (a global nav menu, say) without also adding a third stopScanner() call would leave the camera running in the background, exactly the same underlying bug the React-based siblings' own cleanup functions exist to prevent automatically.
Where This Course Is Headed
The add-item flow next — combining this chapter's scan result with a manual-entry fallback, a POST endpoint, and Pydantic validation errors surfaced directly to the user.
Hands-On Exercises
Explain why this course's own cleanup discipline is described as a real cost of choosing no framework, contrasting it directly with how the three React-based sibling courses handle the same cleanup problem.
📄 View solutionExplain why showScanView's code calls stopScanner() in two separate places, and what would happen if a third way to leave the scan view were added without a matching third call.
📄 View solutionExplain what the if (!currentStream) return; check inside the scan function actually guards against, and why it's necessary given that requestAnimationFrame keeps calling scan() repeatedly.
📄 View solutionChapter 4 Quick Reference
- Same decoding logic as every sibling course: facingMode: "environment", BarcodeDetector with a ZXing fallback
- Written as plain functions: startScanner/stopScanner, a module-level variable instead of a React ref
- Real cost of no framework: cleanup is manual and explicit at every navigation path — no automatic useEffect equivalent
- Every exit path needs its own stopScanner() call — a successful scan, a cancel button, and any future navigation path added later
- The if (!currentStream) return guard: stops a stale scan loop from continuing after stopScanner() already ran
- Next chapter: Building the Add-Item Flow