简体   繁体   English

如何在 React Native 的 TextInput 组件中获取动态引用和焦点

[英]How to get dynamic ref and focus in TextInput component on React Native

Hello everyone and thank you in advance.大家好,提前谢谢你。

I have a screen, where I dynamically generate TextInput (the default number of generated textInput is 4), but from the parent component you can indicate how many inputs you want to have in the view.我有一个屏幕,我在其中动态生成 TextInput(生成的 textInput 的默认数量为 4),但是您可以从父组件指示视图中有多少输入。

I have managed to dynamize the generation of inputs, but I need to dynamize the references and I can't find a way.我已经设法使输入的生成动态化,但我需要使引用动态化,但我找不到办法。

The way it is at the moment, it works perfect for 4 inputs, but if I create it from the parent component with 2 inputs, it breaks.目前的方式,它非常适合 4 个输入,但如果我从具有 2 个输入的父组件创建它,它就会中断。

This is the code:这是代码:

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


Now works perfectly with 4 inputs, but breack with other number of inputs.现在可以完美地处理 4 个输入,但会破坏其他数量的输入。

Need dynamic refs to pass inside for loop and use it in onChangeText and onKeyPress of TextInput component.需要动态引用传递内部 for 循环并在 TextInput 组件的 onChangeText 和 onKeyPress 中使用它。

Thanks a lot.非常感谢。

I was implements this in OTP input, first we need to create a object that have the all refs.我在 OTP 输入中实现了这个,首先我们需要创建一个具有所有引用的 object。

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

The inputs are an array with the number of elements, in your component add this:输入是一个包含元素数量的数组,在您的组件中添加:

ref={inputsRef.current[index]}

and for access to the reference, use this:要访问参考,请使用:

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

Soooolved!太酷了!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM