#javascript #reactjs #typescript #react-native #loops
Вопрос:
Всем привет и заранее благодарю вас.
У меня есть экран, на котором я динамически генерирую текстовый ввод (по умолчанию количество сгенерированных текстовых вводов равно 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 amp;amp; refSecondInput.current.focus()
: i === 1
? text.length > 0 amp;amp; refThirdInput.current.focus()
: i === 2
amp;amp; text.length > 0 amp;amp; refFourthInput.current.focus()
console.log('PIN: ', pin)
}}
value={pin[i]}
onKeyPress={({ nativeEvent }) => {
nativeEvent.key === 'Backspace' amp;amp;
i === 3 amp;amp; refThirdInput.current.focus() ||
i === 2 amp;amp; refSecondInput.current.focus() ||
i === 1 amp;amp; 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
amp;amp; refFourthInput
}
autoFocus={i === 0 amp;amp; true}
/>
)
}
return (
<View style={{ flexDirection: 'row', justifyContent: 'center' }}>
{inputs}
</View>
)
}
return <>{_getInputs(length || 4)}</>
}
export default PinCode
Теперь отлично работает с 4 входами, но не работает с другим количеством входов.
Нужны динамические ссылки для передачи внутри цикла for и использования его в onChangeText и onKeyPress компонента TextInput.
Большое спасибо.
Ответ №1:
Я реализовал это во вводе OTP, сначала нам нужно создать объект, у которого есть все ссылки.
const inputsRef = React.useRef(inputs.map(() => React.createRef<TextInput>()));
Входные данные представляют собой массив с количеством элементов, в вашем компоненте добавьте это:
ref={inputsRef.current[index]}
и для доступа к ссылке используйте это :
inputsRef?.current[index]?.current?.focus();
Комментарии:
1. Привет, Израиль, спасибо за ваш ответ. Не могли бы вы посмотреть ответ под вашим комментарием? Большое спасибо!!
Ответ №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 amp;amp; text.length > 0 amp;amp; mapRef[i 1].current.focus()
text.length === 0 amp;amp; i > 0 amp;amp; mapRef[i].current.focus()
}}
value={pin[i]}
onKeyPress={({ nativeEvent }) => {
nativeEvent.key === 'Backspace' amp;amp;
i > 0 amp;amp; 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
Комментарии:
1. Это не дает ответа на вопрос, это было бы более уместно в качестве комментария.