I want to integrate qr-scanner to my project. This library is capable of decoding QR-Codes by utilizing the camera. It just needs the reference to a html-video-element and then renders the webcam-stream and optionally some indicators of a QR-code being found to this element.
The easiest component would be something like this:
import { useRef } from "react";
import QrScanner from "qr-scanner";
export const QrComponent = () => {
const videoElement = useRef(null);
const scanner = new QrScanner(videoElement.current, (result) => {
console.log(result)
})
return (
<video ref={videoElement} />
)
}
however, qr-scanner checks, if the passed target-element is already part of the DOM:
if (!document.body.contains(video)) {
document.body.appendChild(video);
shouldHideVideo = true;
}
the video-element will never be added to the DOM, when the QrScanner-object is created. This leads to shouldHideVideo being set to true, which disables the video altogether later in the library-code.
So I think I need some kind of way to react to the video-element being added to the DOM. I thougt about using a MutationObserver (and tried it out by stealing the hook from this page), however I only wanted to print out all mutations using the hook like this:
import { useRef, useCallback } from "react";
import QrScanner from "qr-scanner";
import { useMutationObservable } from "./useMutationObservable";
export const QrComponent = () => {
const videoElement = useRef(null);
const scanner = new QrScanner(videoElement.current, (result) => {
console.log(result)
})
const onMutation = useCallback((mutations) => console.log(mutations), [])
useMutationObservable(document, onMutation)
return (
<video ref={videoElement} />
)
}
however, I never got a single line printed, so to me it seems, as if there are no mutations there.
Did I maybe misunderstand something? How can I react to the video-element being added to the document?
Ok, so I think I didn't provide enough information, but I found it out on my own:
The MutationObserver doesn't work, because I told it to watch document, yet I'm actually inside of a shadowdom with this particular component! So I suspect that mutations to the shadowdom won't be detected.
Also, because I'm inside of a shadowdom, document.contains(videoElem.current) will never be true. So in this particular case I have no better choice, than to copy the code of qr-scanner into my project-tree and adapt as needed.
On another note: useLayoutEffect is a react-hook, that is scheduled to run after DOM-mutations. So that's what I would use if I had to start over with this idea.