Component: QrPreview.jsx
Relevant source files
The following files were used as context for generating this wiki page:
The QrPreview.jsx component is a crucial part of the QR-Tool's user interface, responsible for rendering the visual representation of the generated QR code. It is a presentational component that receives all necessary data and configuration from its parent, App.jsx. Its primary functions are to display the QR code using either Canvas or SVG formats, provide visual feedback on the output dimensions, and handle drag-and-drop events for logo uploads.
The component is optimized for performance using React.memo to prevent re-renders when its props have not changed. It also prioritizes accessibility by generating a descriptive aria-label for the QR code image.
Sources: src/components/QrPreview.jsx:1-83, src/App.jsx:921-928
Architecture and Data Flow
The QrPreview component is instantiated within the main App.jsx component. It receives its state and event handlers as props, making it a controlled component. The data flow is unidirectional, originating from the state managed in App.jsx.
This diagram illustrates the flow of props from the parent App component to QrPreview and its internal rendering components.
Component Props
The behavior and appearance of QrPreview are entirely controlled by the props passed from App.jsx.
| Prop | Type | Description | Source File - -
| qrProps | Object | An object containing all properties for the qrcode.react component, such as value, size, level, fgColor, bgColor, and imageSettings. | src/components/QrPreview.jsx:6, src/App.jsx:560-577 - -
| format | string | Determines the rendering format. Can be 'canvas' or 'svg'. | src/components/QrPreview.jsx:7 - -
| canvasRef | React.RefObject | A ref object to be attached to the div wrapping the <QRCodeCanvas> component. Used by ExportPanel.jsx. | src/components/QrPreview.jsx:8, src/components/ExportPanel.jsx:8 -
| svgRef | React.RefObject | A ref object to be attached to the div wrapping the <QRCodeSVG> component. Used by ExportPanel.jsx. | src/components/QrPreview.jsx:9, src/components/ExportPanel.jsx:9 - -
| qrContent | string | The raw string content of the QR code, used to generate an accessible aria-label. | src/components/QrPreview.jsx:10 -
| onDrop | Function | An optional drag-and-drop event handler, used for logo uploads. It is passed from App.jsx. | src/components/QrPreview.jsx:11, src/App.jsx:650-654 -
Rendering Logic
The component uses a simple conditional check on the format prop to decide whether to render a <QRCodeCanvas> or a <QRCodeSVG> component from the qrcode.react library. Both are wrapped in a div that has the appropriate ref (canvasRef or svgRef) attached for the ExportPanel to access.
Sources: src/components/QrPreview.jsx:13, 52-69, package.json:15
Rendering Flow
The following diagram shows the conditional rendering logic inside the QrPreview component.
Code Example: Conditional Rendering
// src/components/QrPreview.jsx:52-69
{isCanvas ? (
<div
ref={canvasRef}
className="relative w-full aspect-square shadow-2xl ring-2 ring-indigo-100 dark:ring-slate-700 hover:scale-[1.02] transition-transform duration-300"
>
<QRCodeCanvas {...qrProps} style={{ width: '100%', height: '100%' }} />
</div>
) : (
<div
ref={svgRef}
className="relative w-full aspect-square shadow-2xl ring-2 ring-indigo-100 dark:ring-slate-700 hover:scale-[1.02] transition-transform duration-300"
>
<QRCodeSVG {...qrProps} style={{ width: '100%', height: '100%' }} />
</div>
)}
This snippet shows how the isCanvas boolean, derived from the format prop, controls which component is rendered. The qrProps object is spread into the chosen component.
Sources: src/components/QrPreview.jsx:13, 52-69
Features
1. Dynamic Information Display
Above the QR code, a small panel displays the calculated output size in pixels and an estimated physical size in centimeters at 300 DPI. This provides immediate feedback to the user about the dimensions of the final exported image.
// src/components/QrPreview.jsx:31-36
<span>
Xuất: {qrProps.size}×{qrProps.size}px
</span>
<span className="text-indigo-500 dark:text-indigo-400">•</span>
<span>{(qrProps.size / 118.11).toFixed(1)}cm @300DPI</span>
The DPI calculation is based on a hardcoded value of 118.11 pixels/cm, which corresponds to 300 DPI (300 pixels/inch / 2.54 cm/inch).
Sources: src/components/QrPreview.jsx:31-36, src/utils/qr-helpers.js
2. Accessibility
To ensure the component is accessible to users with screen readers, an aria-label is dynamically generated for the main wrapper div. The label includes a preview of the QR code's content, truncated to 50 characters to avoid overly long announcements. This is generated using React.useMemo for optimization.
// src/components/QrPreview.jsx:16-20
const qrLabel = React.useMemo(() => {
const content = qrContent || qrProps.value || '';
const preview = content.length > 50 ? content.slice(0, 50) + '...' : content;
return `Mã QR chứa nội dung: ${preview}`;
}, [qrContent, qrProps.value]);
Sources: src/components/QrPreview.jsx:16-20, 48
3. Drag-and-Drop for Logo
The component's main container is configured to act as a drop zone for files if an onDrop handler is provided. This functionality is used for uploading a logo to be placed in the center of the QR code. The onDragOver event is also handled to allow the drop to occur.
This sequence diagram shows the user interaction for uploading a logo via drag-and-drop.
Conclusion
QrPreview.jsx is a well-defined, reusable component that serves as the visual heart of the QR-Tool. It effectively decouples the rendering logic from the application's business logic by relying entirely on props. Its support for both Canvas and SVG formats, combined with accessibility features and user interaction handlers like drag-and-drop, makes it a flexible and robust solution for displaying QR codes within the application.