mebjas / html5-qrcode

A cross platform HTML5 QR code reader. See end to end implementation at: https://scanapp.org
https://qrcode.minhazav.dev
Apache License 2.0
4.97k stars 970 forks source link

looping in onScanSuccess #862

Open Cerealex-alex opened 11 months ago

Cerealex-alex commented 11 months ago

Hello! I'm having trouble with how the scan works and routing: it gets stuck in onScanSuccess looping without any way to stop it that doesn't involve directly clearing it.

I'm using ReactJs.

To Reproduce Steps to reproduce the behavior:

  1. Render a new html5QrcodeScanner with a onSuccess function
  2. Scan a successful code
  3. Result: the onSuccess function loops endlessly

Expected behavior The onSuccess function should set certain variables depending on the decoded text and then stop. It doesn't need to return anything.

Screenshots If applicable, add screenshots to help explain your problem.

Info:

Additional context I've already tried to set a control variable which stores the decoded text, so at the second loop it should check the decoded text, which would be the same, and then not do anything. However, due to the nature of ReactJs Hooks, it doesn't set variables during the loops, even those not using states. I also tried to "return;" without avail.

Also tried just with a console.log to discard a possible self-call.

Another solution to this problem would be a way to store permissions of camera. That way I could render a new Scanner, grant camera permissions, on the onSuccess function clear the scanner and render a new one with those permissions so the user doesn't have to click over and over on the allowing camera button. But I also can't find a way to do this.

Any help is much appreciated. Thank you

muratcakmaksoftware commented 11 months ago

@Cerealex-alex Maybe this code can help you:

pauseScan: function (freeze = true) {
    const state = barcodeReader.html5QrcodeScanner.getState();
    if (state === Html5QrcodeScannerState.SCANNING) {
        barcodeReader.html5QrcodeScanner.pause(freeze);
    }
},
resumeScan: function () {
    const state = barcodeReader.html5QrcodeScanner.getState();
    if (state === Html5QrcodeScannerState.PAUSED) {
        barcodeReader.html5QrcodeScanner.resume();
    }
},
onScanSuccess: function (decodedText, result) {
    barcodeReader.pauseScan();
    setTimeout(() => {
        barcodeReader.qrActions.resumeScan();
    }, 1200);
    barcodeReader.qrCodeSuccessHandler(decodedText);
},
urosran commented 8 months ago

@Cerealex-alex

I struggled with the same thing and ended up doing something similar to what @muratcakmaksoftware mentioned:

    function onScanSuccess(qrCodeMessage) {
        props.setQrCodeResult(qrCodeMessage)
        pauseScanner()
    }

    const startScanner = () => {
        if (html5QrcodeScanner) {
            html5QrcodeScanner.clear()
        }

        const config = createConfig(props);
        const verbose = props.verbose === true;

        html5QrcodeScanner = new Html5QrcodeScanner(
            qrcodeRegionId,
            config,
            verbose
        );

        html5QrcodeScanner.render(
            onScanSuccess,
            props.qrCodeErrorCallback
        );

        props.setIsScanning(true);
    };

    const pauseScanner = () => {
        if (html5QrcodeScanner) {
            html5QrcodeScanner.pause()
        }
    }

    const resumeScanner = () => {
        if (html5QrcodeScanner) {
            html5QrcodeScanner.resume()
        }
    }