react-qr-reader
react-qr-reader copied to clipboard
iOS doesn't rerender component after grant permissions [BUG]
So, I noticed the difference behavior in chrome android and safari iOS browsers. I have the next code
export const QRCodeScanner = ({ onDecode, onClose, onDecodeError }) => {
const status = useCameraPermission();
const handleResult = useCallback(
(result, error) => {
result && onDecode(result.getText());
},
[onDecode, onDecodeError],
);
return (
<div>
{status === "granted" && (
<QrReader
onResult={handleResult}
constraints={{
aspectRatio: 1,
facingMode: "environment",
}}
videoId="react-qr-reader"
/>
)}
</div>
);
};
And it works for safari because QrReader
component appears to page only AFTER user allows permission, pressing the button "Allow camera" in prompt window in safari IOS browser. And this works great! But the same code doesn't work in chrome in android browser, because the prompt window doesn't appear and user can't to allow permission. I suppose the prompt window in safari browser works outside the component while the prompt window in chrome android works inside it.
So, the next code will works in chrome android but doesn't work in safari IOS. After user allow use the camera and status updated doesn't happen anything.
export const QRCodeScanner = ({ onDecode, onClose, onDecodeError }) => {
const status = useCameraPermission();
const handleResult = useCallback(
(result, error) => {
result && onDecode(result.getText());
},
[onDecode, onDecodeError],
);
return (
<div>
<QrReader
onResult={handleResult}
constraints={{
aspectRatio: 1,
facingMode: "environment",
}}
videoId="react-qr-reader"
/>
</div>
);
};
And I reproduce the hook code. I wrote it, because I can check permissions before the QrReader
will render to my page. And really needed functionality.
export const useCameraPermission = () => {
const [status, setStatus] = useState<PermissionState>();
const checkPermission = useCallback(() => {
!window.navigator && setStatus("granted");
window?.navigator?.permissions
? window.navigator.permissions
.query({ name: "camera" })
.then((status) => {
setStatus(status.state);
})
.catch((err) => err.name === "NotAllowedError" && setStatus("denied"))
: window?.navigator?.mediaDevices
.getUserMedia({ video: true })
.then((stream) => {
stream.active && setStatus("granted");
})
.catch((err) => {
err.name === "NotAllowedError" && setStatus("denied");
});
}, []);
useEffect(checkPermission, [checkPermission]);
return status;
};
Any workaround for solving this?