如何通过循环声明多个useRef变量优化OTP输入框聚焦逻辑?
优化后完整方案
1. 批量生成ref(两种可选方案)
方案A:通用兼容方案(支持动态调整OTP位数)
使用单个ref存储所有输入框的引用,避免Hook调用顺序问题:
// 初始化长度为6的引用数组,对应6位OTP输入框 const otpTextInputs = useRef(Array(6).fill(null));
方案B:固定位数场景适用
如果OTP位数固定为6,可直接生成多个ref组成的数组:
// 注意:此写法仅适用于长度固定的场景,保证Hook调用顺序不变 const otpTextInputs = Array.from({ length: 6 }, () => useRef(null));
2. 精简焦点切换逻辑
完全删除冗余的if-else判断,直接通过索引定位前一个输入框:
注:以下示例默认输入框索引从0开始计数,如果你的原有逻辑索引从1开始,把边界判断改为
index > 1即可
const onOtpKeyPress = index => { return ({nativeEvent: {key: value}}) => { // 退格且当前输入框为空时跳转前一个输入框 if (value === 'Backspace' && otpArray[index] === '') { // 仅当不是第一个输入框时跳转焦点 if (index > 0) { // 方案A用这个写法 otpTextInputs.current[index - 1].focus(); // 方案B替换为下面的写法 // otpTextInputs[index - 1].current.focus(); } } }; };
3. 输入框绑定ref示例
如果是循环渲染输入框,直接绑定对应索引即可:
{Array.from({length: 6}).map((_, index) => ( <TextInput key={index} // 方案A绑定写法 ref={el => otpTextInputs.current[index] = el} // 方案B绑定写法 // ref={otpTextInputs[index]} onKeyPress={onOtpKeyPress(index)} value={otpArray[index]} // 其他原有输入框属性保持不变 /> ))}
如果之前是手动写6个输入框,把原来的ref={firstTextInputRef}替换为对应索引的绑定即可,比如第一个输入框对应index=0,第二个对应index=1以此类推。
优化后代码完全符合DRY原则,后续如果需要调整OTP位数,只需要修改初始化时的数组长度即可,不需要逐个新增ref和判断逻辑。
内容的提问来源于stack exchange,提问作者Kerry
相关产品推荐
相关产品推荐

