React Native 动态生成TextInput如何实现动态ref绑定与聚焦控制
React Native 动态数量验证码输入框适配方案
原代码核心问题
- 违反React Hook使用规则:
useRef不允许在普通函数、循环、条件分支中调用,必须放在组件顶层执行 - 硬编码了4个ref实例,无法适配自定义输入框长度的需求
- 输入跳转、退格回跳、提交逻辑全部写死适配4个输入框场景,长度变化后直接访问不存在的ref导致崩溃
- 验证码状态
pin用普通变量存储,组件重渲染时会被重置,状态无法持久
修正后完整代码
import React, { useRef, useState, useEffect } from 'react' import { TextInputProps, View, TextInput } from 'react-native' interface iPinCode extends TextInputProps { onComplete: (code: string) => void length?: number } const PinCode: React.FunctionComponent<iPinCode> = ({ onComplete, length = 4 }) => { // 输入框样式 const inputStyle = { height: 75, width: 50, fontSize: 26, color: '#FFF', backgroundColor: '#4B4B4B', borderRadius: 15, padding: 8, margin: 4, } // 存储所有输入框ref的数组 const inputRefs = useRef<(TextInput | null)[]>([]) // 存储验证码状态 const [pin, setPin] = useState<string[]>(new Array(length).fill('')) // 长度变化时重置ref数组和验证码状态 useEffect(() => { inputRefs.current = inputRefs.current.slice(0, length) setPin(new Array(length).fill('')) }, [length]) // 生成输入框 const renderInputs = () => { const inputs: JSX.Element[] = [] for (let i = 0; i < length; i++) { inputs.push( <TextInput key={i} style={[inputStyle, { textAlign: 'center' }]} onChangeText={text => { const newPin = [...pin] newPin[i] = text.slice(0, 1) setPin(newPin) // 输入内容后自动跳转到下一个输入框 if (text.length > 0 && i < length - 1) { inputRefs.current[i + 1]?.focus() } // 全部输入完成触发回调 if (newPin.every(val => val.length === 1)) { onComplete(newPin.join('')) } }} value={pin[i]} onKeyPress={({ nativeEvent }) => { // 退格时跳转到上一个输入框 if (nativeEvent.key === 'Backspace' && i > 0 && pin[i].length === 0) { inputRefs.current[i - 1]?.focus() } }} secureTextEntry keyboardType="numeric" maxLength={1} returnKeyType={i === length - 1 ? 'done' : 'next'} onSubmitEditing={() => { const code = pin.join('') onComplete(code) console.log('PIN TO SEND: ', code) }} ref={el => inputRefs.current[i] = el} autoFocus={i === 0} /> ) } return ( <View style={{ flexDirection: 'row', justifyContent: 'center' }}> {inputs} </View> ) } return <>{renderInputs()}</> } export default PinCode
核心改动说明
- 将ref存储改为数组结构,通过回调ref的方式动态绑定每个输入框实例,适配任意长度的输入框数量
- 验证码状态用
useState存储,保证组件重渲染时状态不会丢失 - 所有跳转逻辑改为通用判断,通过当前输入框下标
i和总长度length判断是否需要跳转、跳转目标位置 - 增加可选链
?.调用ref方法,避免ref未初始化时报错 - 增加
length变化的监听逻辑,自定义长度变化时自动重置状态和ref数组
内容的提问来源于stack exchange,提问作者user418385
相关产品推荐
相关产品推荐

