我在使用下面的纯函数扫描条形码时遇到了问题。 我在useeffect中绑定了一个keydown事件,因为我需要查找陷阱代码。 当用户输入值时,它记录得很好,但是扫描仪似乎跳过了一两个字符。
import React, { useState, useEffect, useRef, useCallback } from 'react';
import * as propTypes from 'prop-types';
import styled from 'styled-components';
const ScannerInputWrapper = styled.input`
visibility: hidden;
display: none;
width: 0%;
`;
// the current app context would be passed in as a prop to this function
function ScannerInputField({
handleScannerInput,
isScannerInputDisabled,
isDisabled,
}) {
const [dataEntered, setDataEntered] = useState('');
const [nullarised, setNull] = useState('');
const [scanStarted, setScanStarted] = useState(false);
const inputRef = useRef(null);
useEffect(() => {
document.addEventListener('keydown', handleKeys);
return () => {
document.removeEventListener('keydown', handleKeys);
};
}, [dataEntered]);
// focus on the text box at all points. Context awareness will need to come into this.
useEffect(() => {
inputRef.current.focus();
inputRef.current.select();
}, []);
const handleKeys = useCallback(e => {
e.preventDefault();
if ((e.shiftKey || e.ctrlKey || e.altKey) && e.key.length > 1) {
return;
}
if (e.key === '<') {
setScanStarted(true);
return;
}
if (e.key === '`') {
// scan finished, lets send local data to higher function
// handleScannerInput(dataEntered);
console.log(dataEntered);
setScanStarted(false);
setDataEntered('');
return;
}
if (e.key === 'Enter' && !scanStarted && dataEntered !== '') {
// scan finished, lets send local data to higher function
// handleScannerInput(dataEntered);
console.log(dataEntered);
setDataEntered('');
return;
}
if (e.key.length === 1) {
const code = e.keyCode ? e.keyCode : e.which;
// having to do the below due to running an effect and reading from use state
// causes you to read data incorrectly at high velocity
const val = dataEntered.concat(String.fromCharCode(code));
setDataEntered(val);
}
});
return (
<ScannerInputWrapper
type="text"
onChange={value => setNull(value)}
value={dataEntered}
disabled={isDisabled || isScannerInputDisabled}
ref={inputRef}
tabIndex={-1}
/>
);
}
ScannerInputField.propTypes = {
handleScannerInput: propTypes.func.isRequired,
isScannerInputDisabled: propTypes.bool.isRequired,
isDisabled: propTypes.bool.isRequired,
};
ScannerInputWrapper.whyDidYouRender = true;
export default ScannerInputField;
我知道不是每个人都有扫描仪,但如果有人发现我做错了什么蠢事,我会感激指导。
使用React v16.8.6
ScannerInputWrapper
在渲染上是否很耗费资源?每当用户输入时,由于onChange={value => handleKeys(value)}
(在每次按键时都会创建一个新的回调实例),它将重新渲染。您会尝试在其上使用useCallback
吗?您可以在 React 开发工具中检查渲染频率、突出显示更新,并尝试 why-did-you-render。 - dance2die