React中OTP输入显示星号却修改状态导致无法登录,求解决方法
解决方案:分离原始OTP与显示用掩码
核心思路是用两个状态分别存储真实OTP和用于UI显示的掩码值,避免修改原始OTP导致验证失败。具体实现如下:
1. 拆分状态变量
将原来单一的OTP状态拆分为两个独立变量:
rawOTP:存储用户真实输入的OTP,始终保留原始值用于登录验证displayOTP:存储UI上要显示的内容,负责实现延迟转星号的效果
const [rawOTP, setRawOTP] = useState(''); const [displayOTP, setDisplayOTP] = useState('');
2. 实现延迟掩码逻辑
通过useEffect监听rawOTP的变化,每次输入新字符时先显示真实值,0.5秒后将显示内容替换为对应长度的星号:
useEffect(() => { // 输入新字符时,先同步显示真实值 setDisplayOTP(rawOTP); // 设置定时器,0.5秒后将显示内容转为星号 const timer = setTimeout(() => { setDisplayOTP('*'.repeat(rawOTP.length)); }, 500); // 清理定时器,避免内存泄漏和重复触发 return () => clearTimeout(timer); }, [rawOTP]);
3. 调整输入处理与UI绑定
- 在
onOtpChange中更新原始OTP状态,登录验证时直接使用原始输入值 - 将
OtpInput的value属性绑定到displayOTP,确保UI显示掩码内容
const onOtpChange = (value) => { setRawOTP(value); // 存储真实输入值 if (value.length <= 3) { props.resetLogin(); } else if (value.length === 4) { props.resetResendOtp(); props.login({ username: auth.get('userName'), password: auth.get('password'), otp: value, // 使用原始输入值进行验证 type: "WEB", serial: window.localStorage.getItem("visitorId"), showProfileWizard: true, showEftDialog : true }) } } // 调整OtpInput的value绑定 <div className="mt-3 d-flex justify-content-center flex-column align-items-center"> <h3 className="text-center text-lowercase"> <b>{auth && auth.get('otpTarget')}</b> </h3> <OtpInput shouldAutoFocus onChange={onOtpChange} numInputs={4} isInputNum={true} value={displayOTP} // 绑定显示用的掩码值 separator={<span> </span>} inputStyle={{ width: mobileWidth || tabletWidth ? 40 : 60, height: mobileWidth || tabletWidth ? 40 : 60, backgroundColor: '#EDEDEC', border: 'none', borderRadius: 20, }} focusStyle={{ borderRadius: 20, border: `2px solid ${theme.palette.primary.main}`, outline: 'none', }} /> </div>
方案优势
rawOTP全程保留用户输入的真实OTP,不会被修改,确保登录验证时能正确匹配数据库displayOTP仅负责UI展示,通过定时器实现延迟转星号的需求,完全不影响原始数据- 定时器会在每次输入变化时自动清理,避免多个定时器冲突或内存泄漏
内容的提问来源于stack exchange,提问作者user11989626
相关产品推荐
相关产品推荐

