I am using the react-qr-reader component to build a qr scanner modal for my website.
The modal is created as expected and I can scan different qr codes but after dismissing the ion-modal the scanner keeps the users camera active but stops detecting qr codes.
How can I deactivate the users camera?
In my research I found the following question already asked. There the close function I am using is proposed with
ref.current.stopCamera()
at the end. Somehow I can not define ref because ref is not in "IntrinsicAttributes & QrReaderProps" of the QrReader component.
So, how can I reference the react component and is the close function with the added
ref.current.stopCamera()
the correct way of deactivation the camera?
Thanks for your help!
Here is my code:
export const ScannerModal: React.FC<ScannerProps> = ({ triggerID, handleScannedNode }) => {
const modal = useRef<HTMLIonModalElement>(null);
const scannerConstraints: MediaTrackConstraints = {
}
function onDissMiss(event: CustomEvent<OverlayEventDetail>){
console.log(event)
close()
}
function handleScan(result: string){
close()
handleScannedNode(result)
}
async function close(){
console.log("closing")
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: true,
});
stream.getTracks().forEach(function (track) {
track.stop();
track.enabled = false;
});
//ref.current.stopCamera()
}
return (
<>
<IonModal trigger={triggerID} onWillDismiss={onDissMiss} ref={modal}>
<IonTitle>Scanne einen QR-Code</IonTitle>
<IonPage>
<QrReader constraints={scannerConstraints} ref={}
onResult={(result, error) => {
if (!!result) {
handleScan(result?.getText());
}
if (!!error) {
//console.info(error);
}
}}/>
</IonPage>
</IonModal>
</>
);
};
I tried referencing the QrReader component via:
const reader = useRef(null);
<QrReader constraints={scannerConstraints} ref={reader}
onResult={(result, error) => {
if (!!result) {
handleScan(result?.getText());
}
if (!!error) {
//console.info(error);
}
}}/>
The error I received was:
Property 'ref' does not exist on type 'IntrinsicAttributes & QrReaderProps'.
CodePudding user response:
access the ref, you can use the useRef hook in your component
const reader = useRef(null);
<QrReader constraints={scannerConstraints} ref={reader}
onResult={(result, error) => {
if (!!result) {
handleScan(result?.getText());
}
if (!!error) {
//console.info(error);
}
}}/>
Then, you can stop the camera when you want to close the modal by calling the stopCamera method on the ref.
function close(){
console.log("closing")
reader.current.stopCamera();
}
CodePudding user response:
For everybody finding this thread wanting to just implement a simple react qr scanner:
I found a working solution using this qr-scanner project.
I build my component like this:
import { useRef, useState, useEffect } from 'react';
import { IonModal, IonPage, IonTitle } from '@ionic/react';
import { OverlayEventDetail } from '@ionic/core';
import QrScanner from 'qr-scanner';
interface ScannerProps {
triggerID: string;
}
const QrModal: React.FC<ScannerProps> = ({ triggerID }) => {
const modal = useRef<HTMLIonModalElement>(null);
const video = useRef<HTMLVideoElement>(null);
const [qrScanner, setQrScanner] = useState<QrScanner>();
function onDissMiss(_event: CustomEvent<OverlayEventDetail>) {
close();
}
function handleScan(result: QrScanner.ScanResult) {
//Logic with scanned qr code
}
async function close() {
qrScanner?.stop();
qrScanner?.destroy();
setQrScanner(undefined);
}
useEffect(() => {
if (video.current) {
const qrScanner = new QrScanner(video.current, (result) => handleScan(result), {
highlightScanRegion: true,
});
qrScanner.start();
setQrScanner(qrScanner);
}
// Dependency array missing handleScan, since it should not set Scanner on handleScan change
// eslint-disable-next-line
}, [video.current]);
return (
<>
<IonModal trigger={triggerID} onWillDismiss={onDissMiss} ref={modal}>
<IonTitle>Scan your QR-Code</IonTitle>
<IonPage>
<video ref={video}></video>
</IonPage>
</IonModal>
</>
);
};
export default QrModal;