# qrcode.react renders to SVG or Canvas, and boostLevel can raise the error correction you asked for

> qrcode.react is a React component library that draws QR codes into the DOM as either SVG or Canvas, with the encoder vendored into the source tree and the build driven by a Makefile on top of tsup. It declares an ISC licence in its manifest, ships a single lib directory, and accepts React from 16.8 to 19 as a peer dependency.

**zpao/qrcode.react** — A <QRCode/> component for use with React.

- Repository: https://github.com/zpao/qrcode.react
- Website: https://zpao.github.io/qrcode.react/
- Stars: 4,286 · Forks: 340
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/zpao-qrcode-react

## Two components, with SVG recommended and Canvas kept for a reason

The library exports exactly two components, QRCodeSVG and QRCodeCanvas, and they take the same props. The recommendation is SVG because it is more flexible, and the documentation is careful to add that Canvas may be preferable rather than presenting the choice as settled. The practical difference shows up in what you can do afterwards: an SVG is a DOM tree you can restyle, scale and animate, while a canvas is a bitmap whose pixels are already fixed. That also decides the accessibility story, since the title prop exists as a string assigned to the code for that purpose, and an SVG element can carry it in a way a canvas cannot. The value prop is the other half of the contract: it takes a string, or an array of strings to represent multiple segments, which the encoder can lay out more efficiently than one concatenated string. Installing it is a single command:

```sh
npm install qrcode.react
```

CommonJS require is supported alongside the module syntax the examples use.

## The encoder is a vendored file the Makefile treats as a source input

The QR encoding itself is not written by this project. The Makefile names two source dependencies, src/index.tsx and a file at src/third-party/qrcodegen/index.ts, which is the generator library checked into the tree rather than pulled from a registry. Everything in the published package therefore descends from those two files, and the build rules treat them symmetrically: change either one and the declaration files, the CommonJS build, the ES module build and the bundled demo are all considered stale. Four output targets are declared, the CommonJS entry, the ES module entry and two declaration files, and each one runs the same build:code command. The examples target depends on the ES module build rather than the CommonJS one, so the demo is always built from the modern output. The clean target is worth noticing too: it does not delete anything it did not create, but hands lib and examples to git clean in its ignore-only mode, so anything untracked and ignored in those two directories goes away and the build starts from nothing.

## boostLevel can hand you a stronger code than you asked for

The error correction prop is a four value choice, L, M, Q or H, defaulting to L, and the four levels correspond to roughly 7, 15, 25 and 30 percent of the code that can be lost while the symbol still decodes. Higher levels produce more complex codes. On top of that sits boostLevel, a boolean that defaults to true, and its effect is quiet: if the result can carry a higher error correction level than the one you specified without needing a larger version, the encoder takes it. So a request for L can come back as M, and nothing in the returned component says so. If your design depends on the exact density of the symbol, or on the level as a way of budgeting how much of the code is wasted, this is the switch to turn off, and it is on by default.

## marginSize replaces includeMargin, and floors whatever you pass

One prop carries a deprecation warning in the documentation: includeMargin has been deprecated in v4 and will be removed in a future version, with marginSize named as the replacement. The old prop was a boolean controlling whether a margin of four modules was rendered, defaulting to false. The new one is a number, defaulting to zero, and it does two things the boolean could not. It accepts any value even though the QR specification asks for four, and it converts what you pass with Math.floor, so a fractional margin is silently truncated rather than rejected. When both props are specified, marginSize wins. Nothing throws when the deprecated prop is used, so an existing app keeps rendering after the upgrade and only finds out at the removal, since v4 is the current major line and the boolean still works until the version that takes it away.

## excavate blanks the modules underneath an embedded logo

The imageSettings object embeds a picture in the middle of the code, and the field that decides what happens underneath it is excavate. When it is on, every module the image overlaps is replaced with the background colour, which is what produces a clean edge around the logo rather than a scattering of black squares bleeding into it. The documentation also points at the second use, images with transparency, where not excavating leaves code visible through the transparent parts. Around that field sit the ordinary ones: src for the URI, which becomes the src of an img element in the Canvas version and the href of an inline image in the SVG version, height and width in pixels, x and y as pixel offsets using standard DOM positioning with the top left corner as zero, and opacity from zero to one with a default of one. Leave x and y out and the image is centred.

## crossOrigin has a default of undefined on purpose

One field in imageSettings exists for a reason that only shows up when a hosted logo fails to load. crossOrigin sets the attribute used when fetching the embedded image, and its documented default is undefined, with an explanation attached: undefined behaves in React the way it does for any other prop and excludes the attribute from the DOM node, and that matches HTML behaviour where omitting an attribute is not the same as setting it to an empty string. If you copy a crossOrigin value from another attribute or hard code an empty string, you get the empty string instead of the omitted attribute, and a cross origin image may then be blocked. It is a small detail in a long prop list, and it is the kind that only matters when a logo silently does not appear in a deployed build.

## minVersion is a floor, and the real version is chosen from your value

QR symbols come in 40 versions, each larger and denser than the last, and minVersion takes a number from 1 to 40 with a default of 1. The framing matters: it is a lower bound, not a target. The encoder works out the lowest version that can hold the value you passed, and minVersion only raises that floor when the computed version would fall below it. The documented use is producing a consistent minimum density, so a short URL and a long one do not end up as visibly different symbols side by side in a layout. The cost is stated as well, higher versions result in more complex codes, which means more modules for a scanner to read and a denser block at the same pixel size. Both of those props are phrased in terms of the version number, so raising the floor also removes the headroom that boostLevel would otherwise have had to work with.

## The tarball is one directory, and React is a peer dependency

The manifest keeps the published surface narrow. The files array contains a single entry, lib, so the tarball is the build output and nothing else, and sideEffects is false, which tells a consumer's bundler that importing the package has no side effects and its modules can be dropped when unused. React is not a dependency at all; it is a peer dependency accepting 16.8.0, 17, 18 and 19, which is how one release line covers four major versions of React. The build runs through tsup with the target set to es2017 and the platform to browser, producing both module formats and both declaration flavours, where the import condition gets one declaration file and the require condition gets another. The examples are a separate build, an IIFE bundle minified for production with a development variant, published to the project pages site with gh-pages and served locally on port 3000. Publishing is guarded by a prepack script that cleans, rebuilds and then type checks, so a tarball cannot come out of a stale tree, and a separate docs prepublish step runs the clean and build half of that sequence before the pages are pushed.

## Conclusion

qrcode.react fits an application that needs a QR code in the page with the colour, size and embedded logo under its own control, on React anywhere between 16.8 and 19. It does not fit a build that has moved to React Native, since this is a DOM component, and it is a rendering library with no server-side image pipeline. Before adopting it, decide SVG or Canvas once, read how boostLevel interacts with the level you pass, and drop includeMargin in favour of marginSize so your build is not one version away from a removal.

## FAQ

### how to install qrcode react

Run npm install qrcode.react. The package exports QRCodeSVG and QRCodeCanvas, works with CommonJS require as well as module syntax, and lists React from 16.8 through 19 as a peer dependency rather than a bundled one.

### what is qrcode react

It is a React component that generates QR codes for rendering to the DOM. Two components are exported so you can choose SVG, which the documentation recommends as more flexible, or Canvas, which it says may be preferable in some cases.

### Which React versions does qrcode.react support?

React is declared as a peer dependency with a range covering 16.8.0, 17, 18 and 19, so a single release line works across four major React versions. The published package contains only the lib directory and sets sideEffects to false.

### Should I use includeMargin or marginSize in qrcode.react?

Use marginSize. includeMargin has been deprecated in v4 and will be removed in a future version. marginSize takes a number defaulting to zero, converts the value with Math.floor, and overrides includeMargin when both are passed, so the old prop can be left in place without breaking anything yet.

### How do I put a logo in the middle of a qrcode.react code?

Pass an imageSettings object with src for the image URI, plus height, width, and optionally x and y offsets in pixels, opacity between zero and one, and excavate. Excavating replaces the modules the image overlaps with the background colour, which is what gives the logo a clean edge and helps with images that have transparency.

## Sources

- [Issues](https://github.com/zpao/qrcode.react/issues)
- [Project website](https://zpao.github.io/qrcode.react/)
- [README](https://github.com/zpao/qrcode.react/blob/trunk/README.md)
- [Releases](https://github.com/zpao/qrcode.react/releases)
- [zpao/qrcode.react on GitHub](https://github.com/zpao/qrcode.react)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/zpao-qrcode-react
