Mundarija (27)
- Bu darsda
- 1. Nega bu kerak?
- 2. QR kod qanday tuzilgan
- 2.1 Birinchi QR kod
- 2.2 Versiya va xatoni tuzatish darajasi
- 2.3 Markazda logo
- 3. React'da QR: qachon yuklash
- 4. Skanerlash: kamera va BarcodeDetector
- 4.1 Uch shart
- 4.2 BarcodeDetector: bor joyda bepul
- 4.3 Skaner komponenti
- 4.4 Kutubxonalar va biz sinab ko'rgan narsa
- 5. Shtrix-kod: EAN-13
- 6. Hujumchi nigohi
- 7. Vazifalar qadami: vazifa havolasi QR kod bilan (holat 16)
- 7.1 Fayllar
- 7.2 Havola: useHref va basename
- 7.3 Natija
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): bo'sh joylarni to'ldiring
- 2-mashq (o'rta): mehmonlar Wi-Fi QR'i
- 3-mashq (qiyin): skanerlangan shtrix-kodni tekshirish
- 4-mashq: Vazifalar qadami
- 10. Real ishda
- Xulosa
- Manbalar
QR kod React'da: qrcode.react, logo, kamera bilan skanerlash va shtrix-kod
Qisqacha: QR kod — matnni (ko'pincha havolani) qora-oq kvadratchalarga aylantirish. React'da eng qulay yo'l — qrcode.react:
<QRCodeSVG value={havola} level="M" />oddiy SVG chizadi (+6.0 KB gzip, Trusted Types bilan muammosiz). Matn qancha uzun va xatoni tuzatish darajasi (L, M, Q, H) qancha yuqori bo'lsa, kod shuncha zich. Markazga logo qo'yilsa —Hdaraja. Skanerlash uchun kamera kerak (getUserMedia, faqat HTTPS va ruxsat bilan). KodniBarcodeDetector(hamma joyda yo'q) yoki kutubxona taniydi. Kutubxonalardan html5-qrcode (+104.7 KB) Trusted Types ostida ochilmadi, @yudiel/react-qr-scanner (+56.7 KB) WASM'ni CDN'dan yuklaydi.vazifalarda: vazifa havolasi QR kodi — faqat «Ulashish» ochilganda yuklanadigan 6.1 KB chunk.
Bu darsda
qrcode.reactbilan QR kod chizasiz va versiya, xatoni tuzatish darajasi, chet maydonini tushuntirasiz.- Markazga logo qo'yasiz va nega buning uchun
Hdaraja kerakligini bilasiz. - QR komponentini kech yuklaysiz — faqat foydalanuvchi ochganda.
- Kamera bilan skanerlash oqimini (
getUserMedia,BarcodeDetector, tozalash) yozasiz va kutubxonalarni solishtirasiz. - Shtrix-kod (
EAN-13) nazorat raqamini hisoblaysiz va QR orqali firibgarlikdan himoyalanasiz.
Oldin bilishingiz kerak: Rasm UI React'da, Web Audio, kamera va mikrofon (getUserMedia), Clipboard va Web Share API, lazy va code splitting, Suspense.
1. Nega bu kerak?
Oldingi darsda ro'yxatni Excel'ga chiqardik. Endi — ma'lumotni telefonga uzatish. «Bahor» stollarida kichik kartochka turadi: telefon kamerasini to'g'rilasangiz, menyu ochiladi. Kassada esa to'lov QR kodi. Omborda Sardor mahsulot qutisidagi shtrix-kodni skanerlaydi.
QR kod — kompyuterdan telefonga eng tez "ko'prik": havolani qo'lda terish shart emas. vazifalar da ham xuddi shu: kompyuterda ochiq vazifani telefonda davom ettirish uchun QR kod.
Hayotiy o'xshatish: pochta indeksi. Xat tashuvchi manzilni o'qimaydi — indeksni mashina o'qiydi. QR kod ham manzilni odam uchun emas, kamera uchun yozadi.
2. QR kod qanday tuzilgan
2.1 Birinchi QR kod
Natija oynasida qrcode.react 4.2.0 ishlaydi (kanondagi versiya):
import { useEffect, useRef } from "react";
import { QRCodeSVG } from "qrcode.react";
export default function App() {
const ref = useRef(null);
useEffect(() => {
const svg = ref.current;
const attr = (name) => svg.getAttribute(name);
console.log(attr("viewBox"), attr("role"));
console.log(svg.querySelectorAll("path").length, "ta path");
}, []);
return (
<QRCodeSVG
ref={ref}
value="https://example.com/vazifa/2"
size={160}
level="M"
marginSize={2}
title="Vazifa havolasining QR kodi"
/>
);
}Konsolda:
0 0 33 33 img
2 ta path«Ishga tushir» — 160 piksellik QR kod. Telefoningiz kamerasini ekranga to'g'rilang: https://example.com/vazifa/2 taklif qilinadi. Konsoldagi qatorlar ichki tuzilishni ko'rsatadi:
viewBox="0 0 33 33"— kod 33×33 katakdan iborat. Ulardan 29×29 — kodning o'zi, har tomondan 2 katak — chet maydoni (marginSize={2}).- 2 ta path — bittasi oq fon, ikkinchisi — hamma qora kataklar bitta yo'lda. Shuning uchun SVG yengil: 841 katak uchun ikkita element.
role="img"vatitle— Malikaning ekran o'quvchisi uni "Vazifa havolasining QR kodi, rasm" deb o'qiydi.
2.2 Versiya va xatoni tuzatish darajasi
QR kodning o'lchami versiya bilan o'lchanadi: 1-versiya — 21×21 katak, har keyingisi +4, 40-versiya — 177×177. Kutubxona versiyani matn uzunligi va xatoni tuzatish darajasiga qarab o'zi tanlaydi. Daraja — kodning qancha qismi buzilsa (dog', yirtiq, logo) ham o'qilishi:
| Daraja | Tiklanadigan qism (taxminan) |
|---|---|
L |
7% |
M |
15% |
Q |
25% |
H |
30% |
Ikki havola va uch daraja bilan sinaymiz:
import { useEffect, useRef } from "react";
import { QRCodeSVG } from "qrcode.react";
const SHORT = "https://example.com/v/2";
const LONG =
"https://example.com/vazifalar/ru/vazifa/2" +
"?utm_source=qr&utm_medium=stol&utm_campaign=bahor_kuz";
const CASES = [
["qisqa", SHORT, "L"],
["qisqa", SHORT, "M"],
["qisqa", SHORT, "H"],
["uzun", LONG, "M"],
["uzun", LONG, "H"],
];
export default function App() {
const box = useRef(null);
useEffect(() => {
const svgs = box.current.querySelectorAll("svg");
CASES.forEach(([name, value, level], i) => {
const n = svgs[i].getAttribute("viewBox").split(" ")[2];
const version = (n - 17) / 4;
const label = `${name} (${value.length} belgi), ${level}`;
console.log(`${label}: ${n}×${n}, versiya ${version}`);
});
}, []);
return (
<div ref={box}>
{CASES.map(([name, value, level]) => (
<QRCodeSVG
key={name + level}
value={value}
level={level}
size={64}
/>
))}
</div>
);
}Konsolda:
qisqa (23 belgi), L: 25×25, versiya 2
qisqa (23 belgi), M: 25×25, versiya 2
qisqa (23 belgi), H: 29×29, versiya 3
uzun (94 belgi), M: 41×41, versiya 6
uzun (94 belgi), H: 53×53, versiya 9Bu yerda marginSize berilmagan — sukut bo'yicha 0, shuning uchun viewBox = kodning o'zi va (n - 17) / 4 versiyani beradi. Xulosalar:
- Qisqa havola — oddiy kod. 94 belgili havola
Hda 53×53: katakchalar mayda, stol ustidagi kartochkada eski telefon uni qiyin o'qiydi. UTM parametrlari kerak bo'lsa, ularni qisqa havola orqasiga yashiring. M— oqilona sukut. Ekranda (dog' tushmaydi)LyokiMyetadi. Qog'ozda, ayniqsa oshxonada —Q.- Chet maydoni (quiet zone) — kod atrofidagi oq hoshiya. QR standarti 4 katak tavsiya qiladi, kanon 2 qo'ydi va QR'ni oq fonga joyladi (atrofidagi oq ham hoshiya vazifasini bajaradi). Telefon skanerlarini biz sinamadik — o'z loyihangizda albatta sinang. Hoshiyasiz kod qorong'i fonda o'qilmasligi mumkin.
Rang. Skaner qora-oq kontrastga tayanadi. Qorong'i temada QR'ni "teskari" (oq kataklar qora fonda) qilmang — ko'p skanerlar o'qimaydi. Kanon CSS'i shu sababli QR'ga doim oq fon beradi: #qr-kod { background: #fff; }.
Tekshirib ko'ring: Nega qisqa havolada
LvaMbir xil o'lchamli (25×25),Hesa kattaroq?
Javob
Har versiyaga ma'lum miqdorda ma'lumot sig'adi, qolgan joy xatoni tuzatish kodiga ketadi. 23 belgi 2-versiyaga L bilan ham, M bilan ham sig'di — joy yetarli. H esa joyning ko'p qismini tuzatish kodiga beradi va 23 belgi 2-versiyaga sig'may qoldi — kutubxona 3-versiyani tanladi. Daraja oshgani sari bir xil matn uchun kod kattalashadi.
2.3 Markazda logo
Ko'p kompaniyalar QR markaziga logo qo'yadi. Logo kodning bir qismini berkitadi — ya'ni "dog'". Shuning uchun daraja H bo'lishi va logo kichik bo'lishi shart:
import { useEffect, useRef } from "react";
import { QRCodeSVG } from "qrcode.react";
const LOGO =
"data:image/svg+xml," +
encodeURIComponent(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">' +
'<circle cx="5" cy="5" r="5" fill="#1f6f4a"/></svg>',
);
export default function App() {
const ref = useRef(null);
useEffect(() => {
const image = ref.current.querySelector("image");
console.log(image.getAttribute("width"), image.getAttribute("x"));
}, []);
return (
<QRCodeSVG
ref={ref}
value="https://example.com/v/2"
level="H"
size={160}
imageSettings={{
src: LOGO,
width: 32,
height: 32,
excavate: true,
}}
/>
);
}Konsolda:
5.8 11.6imageSettings da width: 32 — piksel (160 lik kod ichida). SVG ichida u katak birligiga o'girilgan: 29 katakli kodda 32/160 × 29 = 5.8 katak, markazda (x = 11.6). Logo kodning ≈ 4% ini egallaydi — H ning 30% zaxirasi bemalol yetadi. excavate: true — logo ostidagi kataklar o'chiriladi: logo shaffof bo'lsa ham qora-oq dog' aralashmaydi.
Qoida: logo kodning eni bo'yicha beshdan biridan oshmasin va har doim haqiqiy telefonlarda sinab ko'ring — eski telefon va yomon yorug'likda ham.
3. React'da QR: qachon yuklash
QR kod har sahifada kerak emas — faqat foydalanuvchi «Ulashish» ni bosganda. qrcode.react kichik (+6.0 KB), lekin birinchi yuklashdagi har kilobayt sezilarli (Yuklanishni optimallashtirish darsida chuqurroq). Kanon QR komponentini lazy bilan ajratdi va uni details tegi ochilgandagina chizadi.
Natija oynasida dinamik import() yo'q, shuning uchun kechikishni Promise bilan taqlid qilamiz (300 ms). Kanon aynan shunday tuzilgan:
import { lazy, Suspense, useState } from "react";
import { QRCodeSVG } from "qrcode.react";
// Loyihada: lazy(() => import("./QrKod.tsx")) — alohida chunk
const QrCode = lazy(
() =>
new Promise((resolve) =>
setTimeout(
() =>
resolve({
default: ({ link }) => (
<QRCodeSVG value={link} size={128} title="QR kod" />
),
}),
300,
),
),
);
export default function App() {
const [open, setOpen] = useState(false);
const link = "https://example.com/vazifa/2";
return (
<details onToggle={(event) => setOpen(event.currentTarget.open)}>
<summary>Ulashish (QR kod)</summary>
{open && (
<Suspense fallback={<p role="status">QR tayyorlanmoqda…</p>}>
<QrCode link={link} />
</Suspense>
)}
<p>
<a href={link}>{link}</a>
</p>
</details>
);
}Ekranda:
Ulashish (QR kod)
QR kod
https://example.com/vazifa/2Uch qadam jadvalda:
| Qadam | Holat | Ekranda |
|---|---|---|
| sahifa ochildi | open — false, chunk so'ralmagan |
«Ulashish (QR kod)» |
| details bosildi | open — true, chunk kutilmoqda |
«QR tayyorlanmoqda…» (ekran() tekshirdi) |
| 300 ms dan keyin | chunk keldi | QR rasmi va havola |
open && … — muhim. Details tegi yopiq bo'lsa ham ichidagi React komponentlari chiziladi (faqat ko'rinmaydi). open state'isiz lazy chunk sahifa ochilishi bilan yuklanardi — kech yuklashdan foyda qolmasdi. onToggle — details ochilib-yopilganda keladigan hodisa.
4. Skanerlash: kamera va BarcodeDetector
4.1 Uch shart
QR'ni o'qish uchun brauzerga kamera kerak (Web Audio, kamera va mikrofon):
- Xavfsiz kontekst — HTTPS yoki
localhost. Oddiyhttp://danavigator.mediaDevicesumuman yo'q. - Ruxsat — brauzer foydalanuvchidan so'raydi. Rad etilsa —
NotAllowedError. SaytningPermissions-Policysarlavhasi kamerani yopib qo'ygan bo'lsa — so'ramaydi ham. Saytimizdagi natija oynasida aynan shunday: kamera yopiq, shuning uchun skaner misollari faqat kod sifatida. - Kodni tanish — videodagi kadrdan QR'ni topish. Buni
BarcodeDetectoryoki kutubxona qiladi.
4.2 BarcodeDetector: bor joyda bepul
BarcodeDetector — brauzerning o'zi shtrix-kod va QR'ni taniydigan API: kutubxonasiz, 0 KB. Muammo — hamma joyda yo'q. Avval imkoniyatni tekshiramiz:
import { useEffect, useState } from "react";
export default function App() {
const [info, setInfo] = useState("tekshirilmoqda…");
useEffect(() => {
if (!("BarcodeDetector" in window)) {
setInfo("BarcodeDetector yo'q — kutubxona kerak");
return;
}
BarcodeDetector.getSupportedFormats().then((formats) =>
setInfo(`bor: ${formats.join(", ")}`),
);
}, []);
return <p>{info}</p>;
}Chrome 155 (Windows, headless) da ekran:
BarcodeDetector yo'q — kutubxona kerakMDN ma'lumotiga ko'ra, API Android va macOS'dagi Chromium brauzerlarida bor, Windows'dagi Chrome'da esa yo'q. Telefoningizda «Ishga tushir» ni bosib ko'ring — natija boshqacha bo'lishi mumkin. Demak, BarcodeDetector — progressiv qo'shimcha (progressive enhancement): bor bo'lsa — ishlatamiz, bo'lmasa — kutubxona yoki havolani qo'lda kiritish.
4.3 Skaner komponenti
Skaner — kamera oqimi + kadr sikli + tozalash. Kod hujjat bo'yicha (natija oynasida kamera yopiq):
function QrScanner({ onResult }) {
const video = useRef(null);
const [error, setError] = useState("");
useEffect(() => {
if (!("BarcodeDetector" in window)) {
setError("Skaner yo'q — havolani qo'lda kiriting.");
return;
}
const detector = new BarcodeDetector({ formats: ["qr_code"] });
let stream = null;
let frame = 0;
let stopped = false;
navigator.mediaDevices
.getUserMedia({ video: { facingMode: "environment" } })
.then(async (s) => {
if (stopped) {
s.getTracks().forEach((t) => t.stop()); // kech keldi
return;
}
stream = s;
video.current.srcObject = s;
await video.current.play();
const tick = async () => {
if (stopped) return;
const [code] = await detector.detect(video.current);
if (code) onResult(code.rawValue);
else frame = requestAnimationFrame(tick);
};
tick();
})
.catch((e) =>
setError(
e.name === "NotAllowedError"
? "Kameraga ruxsat berilmadi."
: "Kamera ochilmadi.",
),
);
return () => {
stopped = true;
cancelAnimationFrame(frame);
stream?.getTracks().forEach((t) => t.stop()); // chiroq o'chadi
};
}, [onResult]);
return (
<>
<video ref={video} muted playsInline aria-label="Kamera" />
{error && <p role="alert">{error}</p>}
</>
);
}Eng muhim qatorlar — tozalashda:
track.stop()— usiz kamera yoniq qoladi: telefonda yashil chiroq yonib turadi, batareya tugaydi, foydalanuvchi qo'rqadi. Komponent yopilganda kamera albatta o'chsin.stoppedbayrog'i — dev rejimidagi StrictMode effektni ikki marta ishga tushiradi. BirinchigetUserMediajavobi tozalashdan keyin kelishi mumkin — u holda oqimni darhol to'xtatamiz. Bu "poyga" (race condition) — kamera bilan ishlashdagi eng ko'p uchraydigan xato.facingMode: "environment"— telefonning orqa kamerasi.- Topilgach to'xtash — natija bitta kerak, sikl davom etmaydi.
4.4 Kutubxonalar va biz sinab ko'rgan narsa
BarcodeDetector yo'q joyda kutubxona kadrni o'zi tahlil qiladi. Kanon ikkitasini vazifalar CSP'si va Trusted Types ostida o'lchadi:
qr-skaner-html5 JS 174889 (+ 104.7 KB) CSS 0 | CSP require-trusted-types-for×1 | xato: This document requires 'TrustedHTML' assignment. The action has been blocked. ; Failed to set the 'innerHTML' property on 'Element': This document requires 'TrustedHTML' assignment | ochiq: tashqi yo'q
qr-skaner-yudiel JS 125735 (+ 56.7 KB) CSS 0 | CSP connect-src×2,script-src×1,media-src×1 | xato: Connecting to 'https://fastly.jsdelivr.net/npm/zxing-wasm@3.1.3/dist/reader/zxing_reader.wasm' viola ; Fetch API cannot load https://fastly.jsdelivr.net/npm/zxing-wasm@3.1.3/dist/reader/zxing_reader.wasm | ochiq: tashqi fastly.jsdelivr.net- html5-qrcode (2.3.8, +104.7 KB) — o'z interfeysini
innerHTMLbilan chizadi → Trusted Types to'sdi. CSP'siz ochilganda esa headless Chrome'da kamera yo'q edi va kutubxona aniq xato berdi:Error getting userMedia, error = NotAllowedError: Permission. Paket 2023-yildan yangilanmagan. - @yudiel/react-qr-scanner (2.6.0, +56.7 KB) —
BarcodeDetectorbor bo'lsa uni ishlatadi, yo'q bo'lsa zxing kutubxonasining WebAssembly versiyasini oladi. WASM fayl esa sukut bo'yicha jsDelivr CDN'dan yuklanadi — CSPconnect-srcvascript-srcda to'sdi. CSP'siz — tashqi hostfastly.jsdelivr.net. Ya'ni foydalanuvchi skanerni ochganda brauzeri uchinchi tomon serveriga murojaat qiladi. WASM faylni o'z serveringizdan berish mumkin — hujjatdagi sozlama bilan; biz buni o'lchamadik.
- uqr 0.1.3 (yaratish)CSP 03,9 KB
- qrcode.react 4.2.0 (yaratish)CSP 0, kanonda6 KB
- qrcode 1.5.4 (yaratish)CSP 08,7 KB
- @yudiel/react-qr-scanner 2.6.0WASM — jsDelivr'dan56,7 KB
- html5-qrcode 2.3.8TT to'sdi104,7 KB
Manba: O'lchandi: kanon tajribasi, Vite 8.3.3, gzip -9, Chrome 155, natijalar/tajriba/kutubxonalar-21.txt, 2026-10-17
Yaratish arzon (4–9 KB), o'qish — qimmat (57–105 KB). Uchta yaratuvchidan uqr eng kichik, lekin u SVG'ni satr qilib beradi — uni sahifaga qo'yish uchun Blob → <img> yoki innerHTML (Trusted Types) kerak. qrcode.react esa React elementlarini qaytaradi. Kanon shuning uchun uni tanladi.
Tekshirib ko'ring: Nega skaner komponentida
useEffectbog'liqligidaonResultbor va bu qanday muammo tug'dirishi mumkin?
Javob
onResult effekt ichida ishlatiladi — demak, u bog'liqlik (useEffect II). Agar ota komponent har renderda yangi funksiya bersa (onResult={(v) => …}), har renderda effekt qayta ishlaydi: kamera o'chadi va qayta yonadi — miltillash. Davosi: otada useCallback, yoki skaner ichida useEffectEvent bilan onResult ni reaktiv bo'lmagan qilish.
5. Shtrix-kod: EAN-13
Do'kondagi mahsulotlar qutisida — shtrix-kod (barcode): vertikal chiziqlar va ostida 13 raqam (EAN-13). Birinchi raqamlar — GS1 tashkilotining mamlakat prefiksi (O'zbekiston — 478), keyin ishlab chiqaruvchi va mahsulot, oxirgisi — nazorat raqami. U skanerlash xatosini ushlaydi: bitta raqam noto'g'ri o'qilsa, nazorat raqami mos kelmaydi.
Hisob oddiy: dastlabki 12 raqam, toq o'rindagilar ×1, juft o'rindagilar ×3, yig'indi. Nazorat raqami — yig'indini 10 ga yaxlitlash uchun yetishmagan son:
function ean13CheckDigit(first12) {
const sum = [...first12].reduce((total, digit, i) => {
const weight = i % 2 === 0 ? 1 : 3;
return total + Number(digit) * weight;
}, 0);
return (10 - (sum % 10)) % 10;
}
console.log(ean13CheckDigit("400638133393")); // 1
console.log(ean13CheckDigit("478123456789")); // 24006381333931 — standartdagi mashhur misol: hisob 1 berdi, haqiqiy oxirgi raqam ham 1. Ikkinchi qator — o'ylab topilgan O'zbekiston kodi uchun nazorat raqami. Oxiridagi % 10 — yig'indi 10 ga bo'linsa, 10 - 0 = 10 emas, 0 bo'lsin.
Shtrix-kod chizish uchun JsBarcode kabi kutubxonalar bor (biz o'lchamadik), o'qish — o'sha BarcodeDetector (formats: ["ean_13"]) yoki skaner kutubxonalari. Kassada esa ko'pincha USB skaner ishlatiladi — u klaviatura kabi ishlaydi: raqamlarni "yozadi" va Enter bosadi. Ya'ni oddiy <input> + onKeyDown yetadi.
6. Hujumchi nigohi
QR kod odamga ko'rinmaydi — u nima ochishini faqat skanerlagach bilamiz. Firibgarlar shundan foydalanadi:
- Quishing (QR phishing) — restoran stolidagi yoki avtoturargohdagi to'lov QR'i ustiga boshqa stiker yopishtiriladi. Mijoz "to'lov sahifasi" ga o'xshash soxta saytga kiradi va karta ma'lumotini kiritadi. Bu O'zbekistonda ham, butun dunyoda ham uchraydigan firibgarlik usuli.
- Ilovangiz skanerlasa — natijani avtomatik ochmang.
new URL(raw)bilan tahlil qiling, faqat kutilgan domen va yo'lni qabul qiling (masalan,location.originva/vazifa/), qolganida — "Bu havola bizniki emas: example.org" deb ko'rsating. - QR'ga sir yozmang. QR — rasm: ekran suratiga, kamera kadriga tushadi. Kirish tokeni, bir martalik parol yoki shaxsiy ma'lumot QR'ga qo'yilsa, uni har kim o'qiydi. Kanon QR'ga faqat vazifa havolasini yozadi; ro'yxatning o'zi — shu brauzerda.
Bu holatlarda xavfsiz yechim — interfeysda domenni ko'rsatish: QR yonida havola matni turadi (kanonda shunday), foydalanuvchi qayerga ketayotganini ko'radi.
7. Vazifalar qadami: vazifa havolasi QR kod bilan (holat 16)
7.1 Fayllar
git switch -c feat/qr
npm i -E qrcode.react@4.2.0Yangi papka src/xususiyatlar/ulashish/: QrKod.tsx, VazifaUlashish.tsx, index.ts. VazifaUmumiy.tsx ga bitta qator, asos.css ga QR stillari.
QrKod.tsx — butun fayl (kanon):
// QrKod.tsx — havola QR kodi (21/#16): qrcode.react 4.2.0,
// SVG React elementlari (innerHTML yo'q — Trusted Types bilan
// ishlaydi). Alohida chunk: faqat «Ulashish» ochilganda
// yuklanadi. O'lchov (kutubxonalar-21): qrcode.react +6.0 KB,
// uqr +3.9 (SVG satr → blob: rasm), qrcode +8.7
import { QRCodeSVG } from "qrcode.react";
export default function QrKod({ havola }: { havola: string }) {
return (
<QRCodeSVG
id="qr-kod"
value={havola}
size={160}
marginSize={2}
level="M"
title="Vazifa havolasining QR kodi"
role="img"
/>
);
}export default — lazy(() => import("./QrKod.tsx")) shuni kutadi.
7.2 Havola: useHref va basename
VazifaUlashish.tsx dagi eng nozik qator — havolani yasash:
const havola = new URL(useHref(`/vazifa/${id}`), location.origin)
.href;/vazifa/2 ni o'zingiz yozsangiz, ikki narsa yo'qoladi: GitHub Pages'dagi papka (/vazifalar/) va til (/ru/) — i18n II darsida ular router basename iga kirgan. useHref — router'ning o'zidan to'liq yo'l: /vazifalar/ru/vazifa/2. new URL(…, location.origin).href — domen bilan to'liq manzil: telefonga aynan shu kerak.
Nusxalash tugmasi Clipboard API bilan, xatosi ham o'ylangan:
async function nusxala() {
try {
await navigator.clipboard.writeText(havola);
setXabar("Havola nusxalandi.");
} catch {
// Ruxsat berilmagan yoki xavfsiz kontekst emas —
// havola ko'rinib turibdi
setXabar("Nusxalab bo'lmadi — havolani belgilab oling.");
}
}Va halol cheklov — kanon komponenti ichida yozilgan: "Ro'yxat shu brauzerda: boshqa qurilmada o'sha qurilmaning ro'yxati ochiladi." Kirish (auth) yo'q — telefon o'z ro'yxatini ochadi, kompyuterdagini emas. Bu TEXNIK-QARZ 64, 28-qismda haqiqiy kirish (Ro'yxat va login oqimi) bilan yechiladi.
7.3 Natija
e2e-21 — 47 ta, QR'ga oidlari:
✅ yopiq: QR chunk yuklanmagan, havola to'liq: [false,"http://127.0.0.1:5718/vazifa/1"]
✅ ochildi: QR (SVG, role=img, nomi), 160 px, chunk keyin yuklandi: ["svg","img","Vazifa havolasining QR kodi",160,true]
✅ QR chunk — ochilgandan keyin: true
✅ nusxalash: xabar, clipboard'da havola: ["Havola nusxalandi.","http://127.0.0.1:5718/vazifa/1"]
✅ QR: CSP buzilishi yo'q: []
✅ Pages/ru: havola /vazifalar/ru/vazifa/2: "/vazifalar/ru/vazifa/2"Birinchi va uchinchi qator — kech yuklash isboti: yopiq holatda QR chunk'i tarmoqda yo'q, ochilgandan keyin keldi. Oxirgisi — useHref GitHub Pages va rus tilida to'g'ri yo'l berdi.
Narx: QR chunk'i — 6.1 KB gzip (faqat ochilganda). Birinchi yuklash — 222.2 → 222.5 KB (+0.3: VazifaUlashish va lazy chaqiruvi). axe — 0, yangi ko'rinish «ulashish ochiq (QR kod)» bilan. node:test 233, Vitest 65 — o'zgarmadi (yangi sof funksiya yo'q, xulq e2e'da).
git add -A
git commitCommit (kanon): feat: vazifa havolasi — QR kod (qrcode.react, kech) va nusxalash.
8. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| telefon QR'ni o'qimaydi | havola juda uzun, kod zich | qisqa havola, M daraja |
| logoli QR o'qilmaydi | daraja L/M yoki logo katta |
level="H", logo ≤ 1/5, excavate |
| qorong'i temada o'qilmaydi | teskari ranglar yoki fon shaffof | doim oq fon, qora katak |
| QR chunk sahifa bilan yuklandi | open && shartisiz details ichida |
ochilganda chizish |
| GitHub Pages'da havola 404 | /vazifa/2 qo'lda, basename yo'q |
useHref |
| kamera chirog'i o'chmaydi | track.stop() yo'q |
tozalash funksiyasida |
navigator.mediaDevices undefined |
http:// (xavfsiz emas) |
HTTPS yoki localhost |
requires 'TrustedHTML' |
html5-qrcode innerHTML |
boshqa kutubxona yoki BarcodeDetector |
9. Mashqlar
Mashqlar kurs/mashqlar/21/16-qr-kod/ da. Jonli yechimlarni «Ishga tushir» bilan sinang.
1-mashq (oson): bo'sh joylarni to'ldiring
- 1-versiyali QR kod ×21 katak
- Logo qo'yilganda kerak bo'ladigan daraja:
level="" - Kamera faqat yoki
localhostda ishlaydi - Kamera oqimini to'xtatadigan metod:
track.() - O'zbekistonning
EAN-13prefiksi:
Yechim
- 21 — har keyingi versiya +4: 2-versiya 25×25.
- H — 30% gacha buzilish tiklanadi, logo shu zaxiradan foydalanadi.
- HTTPS — xavfsiz kontekst; aks holda
navigator.mediaDevicesyo'q. - stop — har trek uchun; usiz kamera yoniq qoladi.
- 478 — GS1 O'zbekiston prefiksi.
2-mashq (o'rta): mehmonlar Wi-Fi QR'i
«Bahor» mehmonlari uchun Wi-Fi QR: telefon uni skanerlasa, tarmoqqa o'zi ulanadi. Format: WIFI:T:WPA;S:<nom>;P:<parol>;;. Nom va parolda \, ;, ,, : va " belgilari oldiga \ qo'yiladi. wifiText(ssid, password) funksiyasini yozing va QR chizing (title — «Wi-Fi: Bahor;Mehmon, parol osh:35000. Konsolga QR ichidagi matnni chiqaring.
Ishora: belgilarni qochirish — 14-darsdagi pdfString kabi replace(/[\\;,:"]/g, "\\$&").
Yechim
import { QRCodeSVG } from "qrcode.react";
const escapeWifi = (s) => s.replace(/[\\;,:"]/g, "\\$&");
function wifiText(ssid, password) {
const s = escapeWifi(ssid);
const p = escapeWifi(password);
return `WIFI:T:WPA;S:${s};P:${p};;`;
}
export default function App() {
const ssid = "Bahor;Mehmon";
const text = wifiText(ssid, "osh:35000");
console.log(text);
return (
<figure>
<QRCodeSVG value={text} level="M" title={`Wi-Fi: ${ssid}`} />
<figcaption>Tarmoq: {ssid}</figcaption>
</figure>
);
}Konsolda:
WIFI:T:WPA;S:Bahor\;Mehmon;P:osh\:35000;;Ekranda:
Wi-Fi: Bahor;Mehmon
Tarmoq: Bahor;MehmonQochirishsiz S:Bahor;Mehmon dagi ; maydonni tugatardi: telefon tarmoq nomini «Bahor» deb, «Mehmon» ni esa tushunarsiz maydon deb o'qirdi. Parol QR'da ochiq — bu faqat mehmonlar tarmog'i uchun maqbul (hujumchi nigohidagi "QR'ga sir yozmang" qoidasi: ishchi tarmoq paroli emas).
3-mashq (qiyin): skanerlangan shtrix-kodni tekshirish
Ombor skaneri scanned qatorlarini beradi. checkEan13(code) funksiyasini yozing — u obyekt qaytarsin:
- 13 ta raqam bo'lmasa —
{ ok: false, reason: "13 ta raqam emas" }. - Nazorat raqami mos kelmasa —
{ ok: false, reason: "nazorat raqami noto'g'ri" }. - To'g'ri bo'lsa —
{ ok: true, uz: true/false }(uz— 478 bilan boshlanadimi).
Sinov: 4006381333931, 4781234567892, 4781234567893, 47812345.
Ishora: raqamlar — /^\d{13}$/ (RegExp asoslari); nazorat — «Shtrix-kod: EAN-13» bo'limidagi ean13CheckDigit(code.slice(0, 12)).
Yechim
function ean13CheckDigit(first12) {
const sum = [...first12].reduce((total, digit, i) => {
const weight = i % 2 === 0 ? 1 : 3;
return total + Number(digit) * weight;
}, 0);
return (10 - (sum % 10)) % 10;
}
function checkEan13(code) {
if (!/^\d{13}$/.test(code)) {
return { ok: false, reason: "13 ta raqam emas" };
}
if (ean13CheckDigit(code.slice(0, 12)) !== Number(code[12])) {
return { ok: false, reason: "nazorat raqami noto'g'ri" };
}
return { ok: true, uz: code.startsWith("478") };
}
const scanned = [
"4006381333931",
"4781234567892",
"4781234567893",
"47812345",
];
for (const code of scanned) console.log(code, checkEan13(code));Konsolda:
4006381333931 { ok: true, uz: false }
4781234567892 { ok: true, uz: true }
4781234567893 { ok: false, reason: "nazorat raqami noto'g'ri" }
47812345 { ok: false, reason: '13 ta raqam emas' }Uchinchi kod ikkinchisidan faqat oxirgi raqam bilan farq qiladi — nazorat raqami buni ushladi. Prefiks mahsulot qayerda ro'yxatdan o'tganini bildiradi, qayerda ishlab chiqarilganini emas. /^\d{13}$/ — ^ va $ siz "13 raqam bor" emas, "faqat 13 raqam" tekshiriladi.
4-mashq: Vazifalar qadami
feat/qr branch'ida «Vazifalar qadami» dagi o'zgarishlarni qiling: qrcode.react@4.2.0, ulashish/ papkasidagi uch fayl, VazifaUmumiy.tsx dagi <VazifaUlashish id={vazifa.id} />, QR uchun oq fon.
Yechim
Tekshiruv ro'yxati:
- Vazifa sahifasi → «Ulashish (QR kod)»: DevTools → Network'da
QrKod-….jsfaqat ochilganda keladi (~6 KB gzip). - Telefon kamerasi bilan skanerlang — vazifa havolasi (lokal
npm run devda telefon kompyuterga ulanmaydi — buni deploy qilingan sahifada sinang). - Rus tilida (
/ru/vazifa/2) havola ham/ru/bilan; GitHub Pages'da —/vazifalar/papkasi bilan. - «Havolani nusxalash» — e'lon «Havola nusxalandi.».
- Qorong'i temada QR oq fonda; axe — buzilish yo'q;
npm run build— birinchi yuklash ~222.5 KB.
10. Real ishda
- Restoran va do'konlar — stol QR menyusi, to'lov QR kodlari (O'zbekistonda to'lov ilovalari QR orqali to'lovni keng ishlatadi), chekdagi QR.
- Login va qurilmalar — "telefon bilan kirish" (Telegram Desktop kabi): QR'da bir martalik, qisqa muddatli va serverda tekshiriladigan kod — 28-qismdagi mavzu.
- Ombor va logistika — shtrix-kod skanerlari, ko'pincha klaviatura kabi ishlaydigan USB qurilmalar.
- Intervyu savollari: "QR'ning xatoni tuzatish darajasi nima?", "logoli QR qanday ishlaydi?", "kamerani React'da qanday to'g'ri yopasiz?", "quishing'dan qanday himoyalanasiz?".
Xulosa
- QR: versiya (21×21 dan, +4), daraja L/M/Q/H (7–30%), chet maydoni; qisqa havola — oddiy kod.
- qrcode.react (+6.0 KB):
QRCodeSVG— React elementlari, Trusted Types bilan muammosiz;titlevarole="img". - Logo —
level="H", kichik,excavate; fon doim oq. - QR'ni kech yuklang:
lazy+ details ochilganda; havola yonida matn ham bo'lsin. - Skanerlash: HTTPS, ruxsat,
BarcodeDetector(hamma joyda emas) yoki kutubxona (57–105 KB, CSP muammolari); tozalashdatrack.stop(). EAN-13— nazorat raqami; skanerlangan narsani avtomatik ochmang, QR'ga sir yozmang.
Keyingi dars: Fayl yuklab berish: Blob, a[download] va showSaveFilePicker — vazifalar eksportini foydalanuvchi o'zi tanlagan joyga saqlash va yuklab berishning React'dagi naqshlari.
Manbalar
- ISO/IEC 18004 (QR Code): versiyalar, xatoni tuzatish darajalari, quiet zone
- qrcode.react 4 — github.com/zpao/qrcode.react (
QRCodeSVG,level,marginSize,imageSettings) - MDN: Barcode Detection API (brauzer qo'llovi),
MediaDevices.getUserMedia(),MediaStreamTrack.stop() - ZXing: "Barcode Contents" (WIFI formati) — github.com/zxing/zxing/wiki
- GS1:
EAN-13nazorat raqami, mamlakat prefikslari — gs1.org - Kanon:
vazifalarholat 16,natijalar/tekshiruv-16.txt,16-axe.txt,brauzer-tekshiruv/natija-21-16.txt,natijalar/tajriba/kutubxonalar-21.txt(2026-10-17)
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!