React Native
The same ReactQRCode component works in React Native and Expo apps. It renders through react-native-svg and supports every style, gradient, logo and frame option that the web version does.
Requirements
- React Native 0.82 or later (the New Architecture), or Expo SDK 55+.
- react-native-svg 15 or later.
Installation
Install the library together with react-native-svg. In an Expo app, expo install picks the react-native-svg version that matches your SDK.
$ npx expo install @lglab/react-qr-code react-native-svgExpo Go already includes react-native-svg. In a bare React Native app or an Expo development build, rebuild the app after installing, for example with npx react-native run-android. On iOS, run npx pod-install before the rebuild.
Usage
Import the component as you would on the web. Metro picks the React Native build from the package's react-native export condition, and Expo web keeps using the DOM build.
1import { ReactQRCode } from '@lglab/react-qr-code'23export const Ticket = () => {4 return (5 <ReactQRCode6 value='https://reactqrcode.com'7 size={240}8 dataModulesSettings={{ style: 'rounded' }}9 frameSettings={{ style: 'banner-bottom', text: 'Scan me!' }}10 />11 )12}
Exporting a PNG
There is no file download on a phone, so the native ref has no download(). Use toDataURL() instead. It resolves with a PNG data URL that is size pixels wide, the same as the component's size unless you pass one. The web ref has the same method.
1import { useRef } from 'react'2import { Button } from 'react-native'3import { ReactQRCode, type ReactQRCodeRef } from '@lglab/react-qr-code'45export const Share = () => {6 const ref = useRef<ReactQRCodeRef>(null)78 const exportPng = async () => {9 // Resolves with "data:image/png;base64,..."10 const png = await ref.current?.toDataURL({ size: 1024 })11 // Show it with <Image source={{ uri: png }} />, or write the base6412 // part to a file with expo-file-system and share it.13 }1415 return (16 <>17 <ReactQRCode ref={ref} value='https://reactqrcode.com' />18 <Button title='Export PNG' onPress={exportPng} />19 </>20 )21}
Logos
imageSettings.src takes a URL or a bundled image from require().
1<ReactQRCode2 value='https://reactqrcode.com'3 imageSettings={{4 src: require('./assets/logo.png'),5 width: 48,6 height: 48,7 excavate: true,8 }}9/>
Differences from the web
- ref.current.svg is the react-native-svg Svg instance, and the ref has toDataURL() but no download().
- svgProps are react-native-svg SvgProps, so use testID, style and accessibility props there.
- Frame labels use the system font by default. To use another, load it in your app (for example with expo-font) and pass its name as frameSettings.fontFamily.
- Labels too long for the frame are squeezed horizontally to fit, because react-native-svg does not support textLength.
- imageSettings.crossOrigin has no effect.
Expo web
On Expo web the package loads its DOM build, so web rules apply there: pass imageSettings.src as a URL rather than a require(), and keep svgProps to props a DOM svg accepts. TypeScript in an Expo project uses the React Native types, so it will not flag these.
Testing with Jest
The React Native build is an ES module, so add @lglab to the packages Jest transforms. With the jest-expo preset:
1{2 "jest": {3 "preset": "jest-expo",4 "transformIgnorePatterns": [5 "node_modules/(?!(\\.pnpm|react-native|@react-native|@react-native-community|expo|@expo|react-native-svg|@lglab))"6 ]7 }8}