Skip to content

Commit c842da9

Browse files
committed
Refactor to fix permissionChecker timeout reference being reassigned in async function
77:9 error Reassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead
1 parent 457d123 commit c842da9

File tree

1 file changed

+46
-48
lines changed

1 file changed

+46
-48
lines changed

ui/components/app/qr-hardware-popover/base-reader.js

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useRef, useState } from 'react';
1+
import React, { useEffect, useRef, useState, useCallback } from 'react';
22
import log from 'loglevel';
33
import { URDecoder } from '@ngraveio/bc-ur';
44
import PropTypes from 'prop-types';
@@ -30,7 +30,7 @@ const BaseReader = ({
3030
const [urDecoder, setURDecoder] = useState(new URDecoder());
3131
const [progress, setProgress] = useState(0);
3232

33-
let permissionChecker = null;
33+
const permissionCheckerRef = useRef(null);
3434
const mounted = useRef(false);
3535

3636
const reset = () => {
@@ -40,29 +40,7 @@ const BaseReader = ({
4040
setProgress(0);
4141
};
4242

43-
const checkEnvironment = async () => {
44-
try {
45-
const { environmentReady } = await WebcamUtils.checkStatus();
46-
if (
47-
!environmentReady &&
48-
getEnvironmentType() !== ENVIRONMENT_TYPE_FULLSCREEN
49-
) {
50-
const currentUrl = new URL(window.location.href);
51-
const currentHash = currentUrl.hash;
52-
const currentRoute = currentHash ? currentHash.substring(1) : null;
53-
global.platform.openExtensionInBrowser(currentRoute);
54-
}
55-
} catch (e) {
56-
if (mounted.current) {
57-
setError(e);
58-
}
59-
}
60-
// initial attempt is required to trigger permission prompt
61-
// eslint-disable-next-line no-use-before-define
62-
return initCamera();
63-
};
64-
65-
const checkPermissions = async () => {
43+
const checkPermissions = useCallback(async () => {
6644
try {
6745
const { permissions } = await WebcamUtils.checkStatus();
6846
if (permissions) {
@@ -74,15 +52,52 @@ const BaseReader = ({
7452
setReady(READY_STATE.READY);
7553
} else if (mounted.current) {
7654
// Keep checking for permissions
77-
permissionChecker = setTimeout(checkPermissions, SECOND);
55+
permissionCheckerRef.current = setTimeout(checkPermissions, SECOND);
7856
setReady(READY_STATE.NEED_TO_ALLOW_ACCESS);
7957
}
8058
} catch (e) {
8159
if (mounted.current) {
8260
setError(e);
8361
}
8462
}
85-
};
63+
}, []);
64+
65+
const initCamera = useCallback(() => {
66+
try {
67+
checkPermissions();
68+
} catch (e) {
69+
if (!mounted.current) {
70+
return;
71+
}
72+
if (e.name === 'NotAllowedError') {
73+
log.info(`Permission denied: '${e}'`);
74+
setReady(READY_STATE.NEED_TO_ALLOW_ACCESS);
75+
} else {
76+
setError(e);
77+
}
78+
}
79+
}, [checkPermissions]);
80+
81+
const checkEnvironment = useCallback(async () => {
82+
try {
83+
const { environmentReady } = await WebcamUtils.checkStatus();
84+
if (
85+
!environmentReady &&
86+
getEnvironmentType() !== ENVIRONMENT_TYPE_FULLSCREEN
87+
) {
88+
const currentUrl = new URL(window.location.href);
89+
const currentHash = currentUrl.hash;
90+
const currentRoute = currentHash ? currentHash.substring(1) : null;
91+
global.platform.openExtensionInBrowser(currentRoute);
92+
}
93+
} catch (e) {
94+
if (mounted.current) {
95+
setError(e);
96+
}
97+
}
98+
// initial attempt is required to trigger permission prompt
99+
return initCamera();
100+
}, [initCamera]);
86101

87102
const handleScan = (data) => {
88103
try {
@@ -105,30 +120,14 @@ const BaseReader = ({
105120
}
106121
};
107122

108-
const initCamera = () => {
109-
try {
110-
checkPermissions();
111-
} catch (e) {
112-
if (!mounted.current) {
113-
return;
114-
}
115-
if (e.name === 'NotAllowedError') {
116-
log.info(`Permission denied: '${e}'`);
117-
setReady(READY_STATE.NEED_TO_ALLOW_ACCESS);
118-
} else {
119-
setError(e);
120-
}
121-
}
122-
};
123-
124123
useEffect(() => {
125124
mounted.current = true;
126125
checkEnvironment();
127126
return () => {
128127
mounted.current = false;
129-
clearTimeout(permissionChecker);
128+
clearTimeout(permissionCheckerRef.current);
129+
permissionCheckerRef.current = null;
130130
};
131-
// eslint-disable-next-line react-hooks/exhaustive-deps
132131
}, []);
133132

134133
useEffect(() => {
@@ -137,11 +136,10 @@ const BaseReader = ({
137136
} else if (ready === READY_STATE.NEED_TO_ALLOW_ACCESS) {
138137
checkPermissions();
139138
}
140-
// eslint-disable-next-line react-hooks/exhaustive-deps
141-
}, [ready]);
139+
}, [ready, checkPermissions, initCamera]);
142140

143141
const tryAgain = () => {
144-
clearTimeout(permissionChecker);
142+
clearTimeout(permissionCheckerRef.current);
145143
reset();
146144
checkEnvironment();
147145
};

0 commit comments

Comments
 (0)