Library / SDK
rosskhanas/react-qr-code avatar
rosskhanas/react-qr-code

react-qr-code: a QR code component that works in the browser and on a phone

A QR code generator for React and React Native.

895 stars89 forksJavaScriptMIT

At a glance

What is it?
react-qr-code is a small React component that renders a QR code as SVG, works in React Native through react-native-svg, and encodes text in UTF-8 so non-ASCII content scans correctly. It suits anyone who needs a QR code in a React app rather than an image asset.
Who is it for?
react-qr-code is a good fit for a React or React Native app that needs a QR code generated from data the user supplies, particularly if that data is not plain ASCII, since UTF-8 byte mode is the default rather than an opt-in. It is the wrong tool if you need a static image file, a dynamic QR code with a logo overlay, or a version that works without a React renderer.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 69 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The whole component in three lines

The usage example is the shortest thing in the documentation, and it sets the tone of the library:

javascript
import React from "react";
import ReactDOM from "react-dom";
import QRCode from "react-qr-code";

ReactDOM.render(<QRCode value="hey" />, document.getElementById("Container"));

One import, one element, one required prop. There is no configuration object, no imperative handle and no separate canvas or image to manage, because the component renders SVG markup into the React tree, which means it scales without blurring and takes styling from the surrounding page. The dependency list explains where the actual encoding happens, since the package depends on prop-types for the runtime prop checks and on qrcode-generator for the QR encoding itself, with react as a peer dependency so that the host application controls the React version. That is a sensible split for a component library, since a library that bundles its own React copy produces the duplicate React problem that breaks hooks. The package is small enough that the whole public surface fits in a table, which is the sign of a component that does one thing.

The prop table is small, and one prop is web only

The API section lists six props, and the platform column is the interesting part because it is not uniform. bgColor is a string defaulting to #FFFFFF and fgColor is a string defaulting to #000000, and both work on web, iOS and Android. The level prop is a string taking one of L, M, Q or H, defaulting to L, which is the lowest error correction level, and it also works everywhere. The size prop is a number defaulting to 256, again on all three platforms. The value prop is the string to encode, with no default, and it is required on all platforms. The odd one out is title, which works on web only, and that is a hint about the implementation, since a title attribute is a web concept and has no native equivalent. The size default of 256 is in pixels, and the component is rendered as an SVG with a viewBox, which is why the responsive example sets the width to 100 percent and constrains it with a max width rather than passing a smaller size. A default error correction level of L is a choice worth noticing, since it produces the simplest code, and a caller who needs the code to survive a logo printed over it, or a damaged printout, has to raise the level themselves.

The quiet zone is the failure mode nobody expects

There is one piece of practical advice in the documentation that is worth more than the whole API table, and it concerns the quiet zone. If the QR code is likely to appear next to dark objects, you need to wrap it in a light-coloured container to preserve the quiet zone, and the example given is a div with a white background and 16 pixels of padding. The quiet zone is the blank margin the specification requires around a code so that scanners can find the finder patterns, and if the background is dark or busy, phones fail to scan a code that looks perfectly fine on screen. The fix is a container rather than a prop, which is a little clumsy but has the advantage of not constraining how you lay out the page. The responsive example works the same way, wrapping the component in a div with an automatic height, a centred margin, a max width of 64 and a full width, and then giving the component itself a size of 256 with a style that scales it and a viewBox of 0 0 256 256. The comment notes that max width can be anything instead, since it is the element that limits the width.

UTF-8 byte mode, and how to convince yourself it works

The encoding detail is the one that distinguishes this from a naive implementation, and the documentation is explicit about it. react-qr-code encodes data in UTF-8 byte mode to ensure that non-ASCII text, with Korean, Japanese and emoji given as examples, renders and scans correctly. The API for that is deliberately unremarkable: you pass a normal JavaScript string and no additional encoding is required on your side. The example is a single element with a Korean string and an emoji in the value prop. That matters in practice because a QR scanner that reads a code as Latin-1 will decode non-ASCII content into something different from what was encoded, and the user sees a QR code that scans to the wrong string. The component also states that it adheres to the official QR spec and can store up to 2953 characters in value, which is the byte mode capacity at the highest error correction level, and it is the boundary you would hit first if you tried to encode a URL with a long tracking parameter.

The documentation also describes a way to check the behaviour locally, which is more than most component libraries bother with. You build the demo library bundle in watch mode with the demo-web-watch script in one terminal, run the demo app with the demo script in another, and the demo opens in the browser through Expo, where you type a non-ASCII value such as Korean, Japanese or an emoji into the input. Then you scan the QR code with a phone camera app and the decoded text should match exactly. That is a real end-to-end check, since it tests the encoding against the actual decoder rather than against an assumption about it.

One package, two renderers, and a native build that swaps in

The packaging is the part that shows real care for the React Native audience. The exports map in the package metadata lists several conditions, and the first is a react-native condition pointing at a separate native entry point, then import pointing at the ES module build, then require pointing at the CommonJS build, then a default fallback, and finally the types condition. That ordering matters, because a bundler that understands the react-native condition will pick the native implementation and everything else will use the web one. The main field points at the CommonJS build and the module field at the ES build, with types at a separate declaration file, and the published files list contains only lib and types, so the demo application and the source are not shipped to consumers. The React Native support depends on react-native-svg, and the installation instructions for it are specific, with the package install followed by the CocoaPods step for iOS. The documentation has separate screenshots for the web demo and for Android and iOS, which is a small sign that the native path is exercised rather than merely claimed.

How the library is built and released

The build tooling is conventional and mostly about producing two module formats from one source directory. The build script removes the lib directory and then runs rollup with the configuration file, and the rollup config and the Babel setup at the root are what turn the src directory into the published lib output. The lint script runs eslint with a fix flag over the JavaScript files and then prettier over the same set plus JSON, with the log level set to warn so the output stays quiet. The demo has its own set of scripts, with the web watch mode using Babel to compile src into the demo's lib directory, the demo itself starting inside the demo directory, a build that exports for the web through Expo, and a deploy that pushes the exported output to gh-pages, which is how the live demo site is published. Releases go through release-it with the conventional changelog plugin, and the configuration for that lives in a release-it.json file at the root, with a CHANGELOG.md in the repository alongside it. The release history shows steady small versions, with 2.2.0 on 2026-06-09, 2.1.1 on 2026-06-08 and 2.0.21 on 2026-04-29, and the last push was on 2026-08-16.

Editorial conclusion

react-qr-code is a good fit for a React or React Native app that needs a QR code generated from data the user supplies, particularly if that data is not plain ASCII, since UTF-8 byte mode is the default rather than an opt-in. It is the wrong tool if you need a static image file, a dynamic QR code with a logo overlay, or a version that works without a React renderer. Before adopting it, read the quiet zone note, because a QR code placed on a dark background needs a light container around it to scan, and check the prop table for the title prop, which is web only and will not appear on a native build. The project is MIT licensed, the last push was on 2026-08-16, and the most recent release is 2.2.0 from 2026-06-09.

Frequently asked questions

How do I install react-qr-code?

Install it with npm i react-qr-code. For React Native you also need react-native-svg, so npm i react-native-svg followed by cd ios && pod install. The component requires only a value prop, and the example is ReactDOM.render(<QRCode value="hey" />, document.getElementById("Container")).

Does react-qr-code handle non-ASCII text?

Yes. It encodes data in UTF-8 byte mode so that non-ASCII text such as Korean, Japanese and emoji renders and scans correctly, and you pass a normal JavaScript string with no extra encoding on your side. The documented example is a QRCode element with a Korean string and an emoji in its value prop.

Why will my QR code not scan on a dark background?

The quiet zone needs to be preserved, so if the code is likely to appear next to dark objects you have to wrap it in a light-coloured container. The documented example is a div with a white background and 16 pixels of padding around the QRCode element.

What props does the react-qr-code component accept?

bgColor and fgColor are strings defaulting to #FFFFFF and #000000, level is a string taking L, M, Q or H defaulting to L, size is a number defaulting to 256, and value is the string to encode. The title prop works on web only, and the other five work on web, iOS and Android.

How much data can a react-qr-code code hold?

The component adheres to the official QR spec and can store up to 2953 characters in the value prop. The error correction level is set with the level prop, and the default is L, which is the lowest error correction level and produces the simplest code.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. rosskhanas/react-qr-code on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rosskhanas-react-qr-code.svg)](https://hysenlabs.com/projects/rosskhanas-react-qr-code)

Was this useful?