我已经在这个问题上停留了2天,现在不知道该怎么办...
我有一个自动制表符输入,重点放在keyUp事件的下一个输入元素上。我的挑战是,在填充所有6个输入之后,我需要将输入值存储在状态中,即使用useState。问题是,当我调用函数存储数据时,输入内部的值不会保留。
面临的挑战主要是因为当我继续编辑我的值时,我一直在增加值数组totpCodeValues
,我已经尝试检查长度以确保不会创建扩展所需长度的元素。 (长度= 6),如果我已经填充了所有值并正在编辑其中的一些值,那么我会寻找索引来使数组变异。该问题无法正常运行,并且输入不遵循索引顺序,甚至不更新值。
const TwoFactorPasswordInput: React.FC<TwoFactorInterface> = ({
setTwoFactorStep
}) => {
let elemRefs: any = useRef(
Array.from({ length: 6 }, () => React.createRef())
);
const [totpCodeValues, setTotpCodeValues] = useState<string[]>([]);
const [isDisabledButton, SetIsDisabledButton] = useState<boolean>(true);
useEffect(() => {
const autoTab = (e: any) => {
const BACKSPACE_KEY = 8;
const DELETE_KEY = 46;
let tabindex = e.target.getAttribute('data-index');
let elem: any = null;
tabindex = Number(tabindex);
if (e.keyCode === BACKSPACE_KEY) {
elem = tabindex > 0 && elemRefs.current[tabindex - 1];
} else if (e.keyCode !== DELETE_KEY) {
elem =
tabindex < elemRefs.current.length - 1 &&
elemRefs.current[tabindex + 1];
}
if (elem) {
elem.current.focus();
}
};
document.addEventListener('keyup', autoTab);
return () => {
document.removeEventListener('keyup', autoTab);
};
}, []);
const getValuesFromRefs = () => {
elemRefs.current.map((element: any) => {
console.log('=====INVOKED======');
setTotpCodeValues(oldArray => [...oldArray, element.current.value]);
});
};
const InputChar = (props: any) => {
return (
<Input
data-testid="form-email"
type="text"
data-index={props.index}
maxLength={1}
autoComplete="off"
name="email"
value={totpCodeValues[props.index]}
onChange={e => {
let newCharValue = e.target.value;
console.log('INDEX INSIDE ONCHANGE', props.index);
}}
onBlur={() => {
if (props.index === 5) {
getValuesFromRefs();
SetIsDisabledButton(false);
}
}}
required
ref={props.reference}
/>
);
};
const blocks = Array.from({ length: 6 }, (element, index) => (
<InputChar key={index} index={index} reference={elemRefs.current[index]} />
));
console.log('totp values', totpCodeValues);
return (
<Wrapper>
{T.translate('twoFactorAuthentication.informCode')}
<Form onSubmit={() => {}} data-testid="login-form">
{blocks}
<StyledButton data-testid="form-button" disabled={isDisabledButton}>
{T.translate('twoFactorAuthentication.authenticate')}
</StyledButton>
<NeutralButton onClick={() => setTwoFactorStep(3)}>
{' '}
{T.translate('twoFactorAuthentication.return')}
</NeutralButton>
</Form>
</Wrapper>
);
};
现在,我正在尝试使用getValuesFromRefs
通过引用获取所有值,但仍然没有成功,因为我需要更新SetIsDisabledButton
,如果不更新,则输入就像魅力,但我需要更新并保留这些值。
答案 0 :(得分:0)
我解决了从头开始构建此组件的问题,这是一个更简单的解决方案,如果有人使用refs在持久值中挣扎,我想在功能中共享该解决方案!
export const TwoFactorPasswordInput: React.FC<Props> = ({
setTwoFactorStep,
isAuthenticating,
authenticationError,
setAuthenticationStart,
setAuthenticationSuccess,
setAuthenticationFailure
}) => {
let elemRefs: any = useRef(
Array.from({ length: 6 }, () => React.createRef())
);
const [totpValues, setTotpValues] = useState<string[]>([]);
const [isDisabledButton, setIsDisabledButton] = useState<boolean>(true);
const setTotpValueAtIndex = (index: number) => (
e: React.ChangeEvent<HTMLInputElement>
) => {
const newValues = [...totpValues];
newValues[index] = e.target.value;
setTotpValues(newValues);
};
const totpValueString = totpValues.join('');
useEffect(() => {
const autoTab = (e: any) => {
const BACKSPACE_KEY = 8;
const DELETE_KEY = 46;
let tabindex = e.target.getAttribute('data-index');
let elem: any = null;
tabindex = Number(tabindex);
if (e.keyCode === BACKSPACE_KEY) {
elem = tabindex > 0 && elemRefs.current[tabindex - 1];
} else if (e.keyCode !== DELETE_KEY) {
elem =
tabindex < elemRefs.current.length - 1 &&
elemRefs.current[tabindex + 1];
}
if (elem) {
elem.current.focus();
}
};
document.addEventListener('keyup', autoTab);
return () => {
document.removeEventListener('keyup', autoTab);
};
}, []);
return (
<Wrapper>
{T.translate('twoFactorAuthentication.informCode')}
<Form onSubmit={submitForm} data-testid="login-form">
{[1, 2, 3, 4, 5, 6].map((_, index) => (
<SingleDigitTotpInput
key={index}
data-index={index}
onChange={setTotpValueAtIndex(index)}
reference={elemRefs.current[index]}
/>
))}
{!!authenticationError && (
<Box>{T.translate('twoFactorAuthentication.error')}</Box>
)}
<StyledButton data-testid="form-button" disabled={isDisabledButton}>
{T.translate('twoFactorAuthentication.authenticate')}
</StyledButton>
<NeutralButton
onClick={() => {
setAuthenticationFailure('');
setTwoFactorStep(3);
}}
>
{' '}
{T.translate('twoFactorAuthentication.return')}
</NeutralButton>
</Form>
</Wrapper>
);
};