How to build a QR and Bar Code Reader using React Native

August 05, 2021

How to build a QR and Bar Code Reader using React Native

How to build a QR and Bar Code Reader using React Native

Getting Started

Let’s start a new RN application:

react-native init BitFritScan && cd BitFritScan

Now, we’ll need to install the following libraries in order to build our app:

First Just Follow the Docs : https://www.npmjs.com/package/react-native-qrcode-scanner

If you see aNo permission handler detected error in iOS:

Try this by adding the permissions_path with Permission-Camera

ios/Podfile
platform :ios, '10.0'

target 'AwesomeProject' do
  permissions_path = '../node_modules/react-native-permissions/ios'
  pod 'Permission-Camera', :path => "#{permissions_path}/Camera"
  config = use_native_modules!

Then update yourInfo.plistwith wanted permissions usage descriptions:

	<key>NSCameraUsageDescription</key>
    <string>Our app need your permission to use your camera phone</string>

Then cd ios and run pod install it will install permission

Scan.js (React Native)

import React, {useEffect, useState} from 'react';
import { AuthHeader } from '../../Componets'
import styled from 'styled-components/native';
import GlobalStyles from '../../Componets/GlobalStyles';
import QRCodeScanner from 'react-native-qrcode-scanner';
import { RNCamera } from 'react-native-camera';
import Xml2js from 'react-native-xml2js';
import { StyleSheet,Text,TouchableOpacity } from 'react-native';

const Scan = ({navigation}) => {

  const [Data, SetData] = useState(null);


    const onSuccess = e => { 
        const {type,data}=e;
        if(type==="QR_CODE"){
        let parser = new Xml2js.Parser();
         parser.parseString(data, (err, result)=> {
            console.info(result)
            SetData(result)
         }) 
        }else{
            console.info(e)
            SetData(data)
        }
      }

      useEffect(() => {
        const onBlur = navigation.addListener('blur', () => {
            SetData(null)
        });
        return {onBlur};
      }, [navigation]);

    return (
        <Container style={GlobalStyles.droidSafeArea}>
             <AuthHeader Title={'Scan'} navigation={navigation}/>  
            <ContainerMain>
                {Data?
                 <Text style={styles.centerText}>
                     {JSON.stringify(Data)}
                  </Text>:
                    <QRCodeScanner
                    onRead={onSuccess}
                    reactivate={true}
                    flashMode={RNCamera.Constants.FlashMode.torch}
                    topContent={
                    <Text style={styles.centerText}>
                        Go to{' '}
                        <Text style={styles.textBold}>wikipedia.org/wiki/QR_code</Text> on
                        your computer and scan the QR code.
                    </Text>
                    }
                    bottomContent={
                    <TouchableOpacity style={styles.buttonTouchable}>
                        <Text style={styles.buttonText}>OK. Got it!</Text>
                    </TouchableOpacity>
                    }
                    />
                }
            </ContainerMain> 
        </Container>
    )  
}

const styles = StyleSheet.create({
    centerText: {
      flex: 1,
      fontSize: 18,
      padding: 32,
      color: '#777'
    },
    textBold: {
      fontWeight: '500',
      color: '#000'
    },
    buttonText: {
      fontSize: 21,
      color: 'rgb(0,122,255)'
    },
    buttonTouchable: {
      padding: 16,
    }
  });

const Container = styled.SafeAreaView`
       flex: 1;
       background-color: #343434;
`; 
const ContainerMain = styled.View`
       flex: 1;
       background-color: #ffffff;
`; 

export default Scan;

Scan.js (Expo)

import React, { useState, useEffect } from "react";
import {
  Text,
  View,Platform,StatusBar,
  StyleSheet,Alert,
  TouchableOpacity,
  SafeAreaView,
  Linking,
} from "react-native";
import { useTheme } from "react-native-paper";
import { useNavigation,useIsFocused } from "@react-navigation/native";
import { Button } from "cscommon/lib";
import {Camera} from 'expo-camera'
const Scan = () => {
  const { colors } = useTheme();

  const styles = StyleSheet.create({
    scroll: {
      flex: 1,
      backgroundColor: "white",
    },
    screen: {
      flex: 1,
      backgroundColor: "#F2F2FC",
    },
    saveArea: {
      paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0,
      backgroundColor: colors.secondary, //  '#62d1bc',
    },
    topBar: {
      height: 50,
      backgroundColor: colors.secondary, //'#62d1bc',
      alignItems: "center",
      justifyContent: "center",
    },
    topBarTitleText: {
      color: "#ffffff",
      fontSize: 20,
    },
    caption: {
      height: 120,
      justifyContent: "center",
      alignItems: "center",
    },
    captionTitleText: {
      color: "#121B0D",
      fontSize: 16,
      fontWeight: "600",
    },
    btn: {
      width: 240,
      borderRadius: 4,
      backgroundColor: colors.secondary, //'#62d1bc',
      paddingHorizontal: 24,
      paddingVertical: 12,
      marginVertical: 8,
    },
    btnText: {
      fontSize: 18,
      color: "#ffffff",
      textAlign: "center",
    },
    rnCamera: {
      flex: 1,
      width: "94%",
      alignSelf: "center",
    },
    rmCameraResult: {
      justifyContent: "center",
      alignItems: "center",
      backgroundColor: "#eeeeee",
    },
    rmCameraResultText: {
      fontSize: 20,
      color: "#62d1bc",
    },
    cameraControl: {
      height: 180,
      justifyContent: "center",
      alignItems: "center",
    },
  });

  const [hasPermission, setHasPermission] = useState(null);
  const [scanned, setScanned] = useState(false);
  const navigation = useNavigation();
  const focused = useIsFocused()

  const CallAlert = () => {
    Alert.alert(
      "QR Code",
      "Please check you QR code this is not a valid QR",
      [{ text: "OK", onPress: () => setScanned(false) }],
      { cancelable: false }
    );
  };

  const openSettings = () => {
    if (Platform.OS === "ios") {
      Linking.openURL("app-settings:");
    } else {
      Linking.openSettings();
    }
  };

  const ReqPermission = async () => {
    const {status} = await Camera.requestCameraPermissionsAsync()
    console.info({status})
    setHasPermission(status === "granted");
  };


  useEffect(() => {
    ReqPermission();
  }, []);



  const handleBarCodeScanned = (result) => {
    console.info(result);
    // if(!testvalid){  //USE THIS IF QR CODE IS IN VALID LIKE MISSMATCH CONFIG KEY
    //   CallAlert();
    //   return false;
    // }
    navigation.navigate('Login', {result});
    setScanned(!scanned);
  };



  return (
    <View style={styles.screen}>
      <SafeAreaView style={styles.saveArea}>
        <View style={styles.topBar}>
          <Text style={styles.topBarTitleText}>SSO Login</Text>
        </View>
      </SafeAreaView>
      <>
        {hasPermission === false ? (
          <TouchableOpacity style={{ margin: 15, padding: 15 }}>
            <Text onPress={openSettings} style={styles.captionTitleText}>
              Camera permission is denied you can press 
               <Text style={{color:'blue'}}> here </Text>
               to enable it and retry again
            </Text>
          </TouchableOpacity>
        ) : (
          <>
            <View style={styles.caption}>
              <Text style={styles.captionTitleText}>
                Scan your QR code for login
              </Text>
            </View>
            {focused &&
            <Camera
               key={scanned ? 1 : 2}
               onBarCodeScanned={(result) => {
                handleBarCodeScanned(result);
               }}
               style={styles.rnCamera}
               />
              }
          </>
        )}
        <Stack/>
        {hasPermission === false ? (
            <Button
               style={{margin:8}}
               onPress={()=>{
                ReqPermission();
              }}
              text={'Retry Again to Scan'}
            />
        ):(
          <Button
               style={{margin:8}}
          

              onPress={()=>{
                navigation.navigate('Login')
              }}
              text={'Skip QR Scan'}
            />
        )
        }
      </>
    </View>
  );
};

export default Scan;

Written by Manoj Bhardwaj who lives and works in Dharamshala Himachal Pradesh (India). My stackoverflow