【问题标题】:How to get dynamic ref and focus in TextInput component on React Native如何在 React Native 上的 TextInput 组件中获取动态引用和焦点
【发布时间】:2021-10-06 16:06:02
【问题描述】:

大家好,提前谢谢大家。

我有一个屏幕,我在其中动态生成 TextInput(生成的 textInput 的默认数量是 4),但是您可以从父组件中指示您希望在视图中有多少个输入。

我已经设法使输入的生成动态化,但我需要动态化引用,但我找不到方法。

目前的情况,它适用于 4 个输入,但如果我从具有 2 个输入的父组件创建它,它会中断。

这是代码:

import React, { useRef } 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 }) => {
  
  const inputStyle = {
    height: 75,
    width: 50,
    fontSize: 26,
    color: '#FFF',
    backgroundColor: '#4B4B4B',
    borderRadius: 15,
    padding: 8,
    margin: 4,
  }
  
  const _getInputs = (length: number) => {
    let inputs: JSX.Element[] = []
    
    let pin: string[] = []

    let refFirstInput = useRef()
    let refSecondInput = useRef()
    let refThirdInput = useRef()
    let refFourthInput = useRef()
    
    for (let i = 0; i < length; i++) {      
      inputs.push(
        <TextInput
          key={i}
          style={[inputStyle, { textAlign: 'center' }]}
          onChangeText={text => {
            text.length >= 1 ? pin.splice(i, 0, text) : pin.splice(i, 1)
            i === 0
              ? text.length > 0 && refSecondInput.current.focus()
              : i === 1
              ? text.length > 0 && refThirdInput.current.focus()
              : i === 2
              && text.length > 0 && refFourthInput.current.focus()
              
            console.log('PIN: ', pin)
          }}
          value={pin[i]}
          onKeyPress={({ nativeEvent }) => {
            nativeEvent.key === 'Backspace' &&
            i === 3 && refThirdInput.current.focus() ||
            i === 2 && refSecondInput.current.focus() ||
            i === 1 && refFirstInput.current.focus()
        }}
          secureTextEntry
          keyboardType="numeric"
          maxLength={1}
          returnKeyType={i === 3 ? 'done' : 'next'}
          onSubmitEditing={() => { onComplete(pin.join('')); console.log('PIN TO SEND: ', pin.join(''))}}
          ref={
            i === 0
              ? refFirstInput
              : i === 1
              ? refSecondInput
              : i === 2
              ? refThirdInput
              : i === 3
              && refFourthInput
          }
          autoFocus={i === 0 && true}
          />
      )
    }

    return (
      <View style={{ flexDirection: 'row', justifyContent: 'center' }}>
        {inputs}
      </View>
    )
  }

  return <>{_getInputs(length || 4)}</>
}

export default PinCode


现在可以完美地使用 4 个输入,但会中断其他数量的输入。

需要动态 refs 传入 for 循环,并在 TextInput 组件的 onChangeText 和 onKeyPress 中使用。

非常感谢。

【问题讨论】:

    标签: javascript reactjs typescript react-native loops


    【解决方案1】:

    我是在 OTP 输入中实现的,首先我们需要创建一个具有所有引用的对象。

    const inputsRef = React.useRef(inputs.map(() => React.createRef<TextInput>()));
    

    输入是一个包含元素数量的数组,在你的组件中添加这个:

    ref={inputsRef.current[index]}
    

    要访问参考,请使用:

    inputsRef?.current[index]?.current?.focus();
    

    【讨论】:

    • 您好,以色列感谢您的回复。您能在评论下方看到回复吗?非常感谢!!
    【解决方案2】:

    太棒了!

    import React, { useRef } 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 }) => {
      
      const inputStyle = {
        height: 75,
        width: 50,
        fontSize: 26,
        color: '#FFF',
        backgroundColor: '#4B4B4B',
        borderRadius: 15,
        padding: 8,
        margin: 4,
      }
      
      const _getInputs = (length: number) => {
        let inputs: JSX.Element[] = []
        
        let pin: string[] = []
    
        const mapRef: any = []
        
        for (let index = 0; index < length; index++) {
          mapRef.push(useRef())
        }
        
        for (let i = 0; i < length; i++) {
          inputs.push(
            <TextInput
              key={i}
              style={[inputStyle, { textAlign: 'center' }]}
              onChangeText={text => {
                text.length === 1 ? pin.splice(i, 0, text) : pin.splice(i, 1)
                i < length - 1 && text.length > 0 && mapRef[i + 1].current.focus()
                text.length === 0 && i > 0 && mapRef[i].current.focus()
              }}
              value={pin[i]}
              onKeyPress={({ nativeEvent }) => {
                nativeEvent.key === 'Backspace' &&
                  i > 0 && mapRef[i - 1].current.focus()
              }}
              secureTextEntry
              keyboardType="numeric"
              maxLength={1}
              returnKeyType={length - 1 ? 'done' : 'next'}
              onSubmitEditing={() => onComplete(pin.join(''))}
              ref={mapRef[i]}
              autoFocus={i === 0}
            />
          )
        }
    
        return (
          <View style={{ flexDirection: 'row', justifyContent: 'center' }}>
            {inputs}
          </View>
        )
      }
      return <>{_getInputs(length || 4)}</>
    }
    
    export default PinCode
    
    

    【讨论】:

    • 这并没有提供问题的答案,这将更适合作为评论。
    猜你喜欢
    • 2018-08-07
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 2017-07-11
    • 1970-01-01
    • 2020-06-06
    相关资源
    最近更新 更多