diff --git a/src/index.js b/src/index.js
index 8dd68e6..8105f22 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,122 +1,128 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import PropTypes from 'prop-types'
-import WebWorker from 'web-worker:./worker'
+import * as React from "react";
+import PropTypes from "prop-types";
+import WebWorker from "web-worker:./worker";
-const createWorker = () => new WebWorker()
+const createWorker = () => new WebWorker();
const stopMediaStream = (stream) => {
if (stream) {
if (stream.getVideoTracks && stream.getAudioTracks) {
- stream.getVideoTracks().map(track => {
+ stream.getVideoTracks().forEach((track) => {
stream.removeTrack(track);
track.stop();
});
- stream.getAudioTracks().map(track => {
+ stream.getAudioTracks().forEach((track) => {
stream.removeTrack(track);
track.stop();
});
- }
- else {
+ } else {
stream.stop();
}
}
-}
+};
const Reader = (props) => {
- const { constraints, onError, onLoad, onScan, resolution, ...other } = props
- const constraintsStr = JSON.stringify(constraints)
+ const { constraints, onError, onLoad, onScan, resolution, ...other } = props;
+ const constraintsStr = JSON.stringify(constraints);
- const streamRef = useRef(null)
- const videoEl = useRef(null)
- const canvasEl = useRef(document.createElement('canvas'))
- const ctxRef = useRef(null)
- const requestRef = useRef()
- const [src, setSrc] = useState(null)
+ const streamRef = React.useRef(null);
+ const videoEl = React.useRef(null);
+ const canvasEl = React.useRef(document.createElement("canvas"));
+ const ctxRef = React.useRef(null);
+ const requestRef = React.useRef();
+ const [src, setSrc] = React.useState(null);
- const isProcessingRef = useRef(false)
- const worker = useMemo(createWorker, [createWorker])
+ const isProcessingRef = React.useRef(false);
+ const workerRef = React.useRef();
- useEffect(() => {
- return () => {
- worker.terminate()
- }
- }, [worker])
+ React.useEffect(() => {
+ workerRef.current = createWorker();
+ const worker = workerRef.current;
- useEffect(() => {
worker.onmessage = (e) => {
- if (onScan) onScan(e.data ? { ...e.data, canvas: canvasEl.current } : null)
- isProcessingRef.current = false
- }
- }, [onScan, worker])
+ if (onScan)
+ onScan(e.data ? { ...e.data, canvas: canvasEl.current } : null);
+ isProcessingRef.current = false;
+ };
- const check = useCallback(() => {
- const videoIsPlaying = videoEl.current && videoEl.current.readyState === videoEl.current.HAVE_ENOUGH_DATA
+ return () => {
+ worker.terminate();
+ };
+ }, [onScan]);
+
+ const check = React.useCallback(() => {
+ const worker = workerRef.current;
+
+ const videoIsPlaying =
+ videoEl.current &&
+ videoEl.current.readyState === videoEl.current.HAVE_ENOUGH_DATA;
if (!isProcessingRef.current && videoIsPlaying) {
- isProcessingRef.current = true
+ isProcessingRef.current = true;
// Get image/video dimensions
- let width = videoEl.current.videoWidth
- let height = videoEl.current.videoHeight
+ let width = videoEl.current.videoWidth;
+ let height = videoEl.current.videoHeight;
- const greatestSize = width > height ? width : height
- const ratio = resolution / greatestSize
+ const greatestSize = width > height ? width : height;
+ const ratio = resolution / greatestSize;
- height = ratio * height
- width = ratio * width
+ height = ratio * height;
+ width = ratio * width;
- canvasEl.current.width = width
- canvasEl.current.height = height
+ canvasEl.current.width = width;
+ canvasEl.current.height = height;
- ctxRef.current = canvasEl.current.getContext('2d')
- ctxRef.current.drawImage(videoEl.current, 0, 0, width, height)
- const imageData = ctxRef.current.getImageData(0, 0, width, height)
+ ctxRef.current = canvasEl.current.getContext("2d");
+ ctxRef.current.drawImage(videoEl.current, 0, 0, width, height);
+ const imageData = ctxRef.current.getImageData(0, 0, width, height);
// Send data to web-worker
- worker.postMessage(imageData)
+ worker.postMessage(imageData);
}
- requestRef.current = requestAnimationFrame(check)
- }, [resolution, worker])
+ requestRef.current = requestAnimationFrame(check);
+ }, [resolution]);
- useEffect(() => {
- const constraints = JSON.parse(constraintsStr)
+ React.useEffect(() => {
+ const constraints = JSON.parse(constraintsStr);
- let isSubscribed = true
- navigator.mediaDevices.getUserMedia(constraints)
+ let isSubscribed = true;
+ navigator.mediaDevices
+ .getUserMedia(constraints)
.then((stream) => {
if (!isSubscribed) {
- stopMediaStream(stream)
+ stopMediaStream(stream);
} else {
- streamRef.current = stream
+ streamRef.current = stream;
try {
if (videoEl.current) {
- videoEl.current.srcObject = stream
- videoEl.current.setAttribute('playsinline', true) // required to tell iOS safari we don't want fullscreen
+ videoEl.current.srcObject = stream;
+ videoEl.current.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
}
} catch (error) {
- setSrc(window.URL.createObjectURL(stream))
+ setSrc(window.URL.createObjectURL(stream));
}
- if (onLoad) onLoad()
+ if (onLoad) onLoad();
- requestRef.current = requestAnimationFrame(check)
+ requestRef.current = requestAnimationFrame(check);
}
})
- .catch(error => (isSubscribed ? onError(error) : null))
+ .catch((error) => (isSubscribed ? onError(error) : null));
return () => {
- cancelAnimationFrame(requestRef.current)
- isSubscribed = false
- stopMediaStream(streamRef.current)
+ cancelAnimationFrame(requestRef.current);
+ isSubscribed = false;
+ stopMediaStream(streamRef.current);
if (src) {
window.URL.revokeObjectURL(src);
}
- }
- }, [check, constraintsStr, onError, onLoad])
+ };
+ }, [check, constraintsStr, onError, onLoad, src]);
- return ()
-}
+ return ;
+};
Reader.propTypes = {
constraints: PropTypes.object,
@@ -124,11 +130,11 @@ Reader.propTypes = {
onLoad: PropTypes.func,
onScan: PropTypes.func.isRequired,
resolution: PropTypes.number,
-}
+};
Reader.defaultProps = {
constraints: { audio: false, video: true },
resolution: 640,
-}
+};
-export default Reader
+export default Reader;