Search code examples
react-nativemobilewebviewqr-code

QR Code Scanner and Webview in React Native


Relatively new to React Native. Been trying to get a QR Code Scanner to scan the QR Code and direct the App Screen to a webview to view the URL deciphered from the QR Code. Lots of QR Code packages give examples for displaying the URL but not necessarily do they mention passing on the URL to a webview.

Approach

Here I've set the url to empty string and a variable webview to false. On scanning i'm updating the state for the url after scanning and setting variable webview to true.

Then using conditional rendering to try switch between QR Code scanning and a webview when QR Code is scanned. I've included a button to switch back to the QR Camera.

Problem

The App crashes when it goes to scan a QR code. No errors are apparent in debug mode from xcode. I've had a look at the debugging part of the simulator and no apparent errors, prior to scanning, not too sure how do debug on the iPhone whilst scanning since the app crashes.

On testing the App

Code Snippet

import React, { Component } from 'react'
import { View, TouchableOpacity, Text} from 'react-native'
import QRCodeScanner from 'react-native-qrcode-scanner';
import { RNCamera } from 'react-native-camera';

export default class QR extends Component {
  constructor(props) {
    super(props)
    this.state = {
      webview: false,
      url: ''
    }
  }
  
  onSuccess = e => {
      this.setState({url: e.data, webview: true})
    }
    
  render() {
    return (
      <View style={{flex:1}}>
        <View style={{flex:1}}>
            {this.state.webview && (<Webview 
              source={{uri: this.state.url}}
              style={{flex:1}}
              scalesPageToFit={true} />
              )}

            {!this.state.webview && (<QRCodeScanner
              onRead={this.onSuccess}
              flashMode={RNCamera.Constants.FlashMode.torch}
          /> 
          )}
    
          <TouchableOpacity
            style={{
              alignItems: 'center',
              justifyContent: 'center',
              backgroundColor: 'rgba(0,0,0,0.2)',
              borderRadius: 50,
              width: 50,
              height: 50,
              position: 'absolute',
              right: 5,
              bottom: 5
            }}
            onPress={() => this.setState({ webview: false })}
          >
              <Text> Click Me </Text>
          </TouchableOpacity>
      </View>
    </View>
    );
  }
}

I'd be grateful to know where I'm going wrong here. I've tried numerous other QR Code scanners, I do think my approach should work, but not really seeing the mistake.

Thanks!


Solution

  • Correct. As you have correctly identified the issue, it is a binding issue. The Below code will solve the issue.

    this.onSuccess.bind(this) 
    

    There is one more approach to achieve this. When you import 'react-native-qrcode-scanner' and 'react-native-camera' packages, your app will become bulky. So use any HTML based QR code reader and open it from the WebView.

    return (
      <View style={styles.flex1}>
        <WebView
          source={{uri: '#scannerlink'}}
          startInLoadingState={true}
          onShouldStartLoadWithRequest={event => {
            if (event.url !== '#scannerlink') {
              console.log('onShouldStartLoadWithRequest', event.url);
              // Write your code here.
              return false;
            }
            return true;
          }}
        />
      </View>
    );
    

    On the HTML scanner page, open the URL after the successful scan. Handle this URL change on the react-native code using the function onShouldStartLoadWithRequest()

    There are multiple HTML QR code readers are available. jsqrcode is good one to use it. There is an article on this to show the complete integration if required.