自动关注下一个TextInput onChangeText崩溃

时间:2019-11-10 12:01:06

标签: javascript reactjs react-native

我想用6 TextInput创建一个OTP输入屏幕。我希望TextInput在输入上一个TextInput的值时自动聚焦到下一个。enter image description here

我遵循了the following question.

中给出的解决方案

但是我遇到了一个异常TypeError: null is not an object(evaluating 'textInputToFocus.current.focus'),所以基本上我的变量textInputToFocus在下面的代码中为null,我不确定为什么吗?

import React, { Component } from 'react';
import {
  StyleSheet,
  View,
  Text,
} from 'react-native';
import { PasscodeTextInput } from '../Common/PasscodeTextInput';
import Button from 'react-native-button';

type Props = {}

export default class EnterOTP extends React.Component {

  constructor(props) {
      super(props)
      this.state = {
          passcode1: "",
          passcode2: "",
          passcode3: "",
          passcode4: "",
          passcode5: "",
          passcode6: "",
      }
      this.passcode1 = React.createRef()
      this.passcode2 = React.createRef()
      this.passcode3 = React.createRef()
      this.passcode4 = React.createRef()
      this.passcode5 = React.createRef()
      this.passcode6 = React.createRef()
      this.inputNumber = this.inputNumber.bind(this); 

  }

  onVerify = () => {

  }

  inputNumber(value, flag) {
    const completeFlag = `passcode${flag}`
    console.log(completeFlag);
    console.log(value)
    this.setState({[completeFlag]: value})
    console.log(this.state);
    flag = flag + 1
    if (flag < 7 && value) {
        const nextFlag = `passcode${flag}`
        console.log(nextFlag);
        const textInputToFocus = this[nextFlag]
        console.log(textInputToFocus)
        textInputToFocus.current.focus()
    }
}
  render() {
    return (
    <View style={styles.container}>
        <View style={styles.leftContainer}>
            <Text style = {styles.firstText}>SMS Verification</Text>
            <Text style = {styles.secondText}>We have sent an SMS with a verification code to +91 7777777777. Please enter it below.</Text>
        </View>
        <View style={[styles.passcodeContainer]}>
          <PasscodeTextInput
            autoFocus={true}
            ref={this.passcode1}
            onChangeText={number => this.inputNumber(number, 1)} />
          <PasscodeTextInput
            ref={this.passcode2}
            onChangeText={number => this.inputNumber(number, 2)} />
          <PasscodeTextInput
            ref={this.passcode3}
            onChangeText={number => this.inputNumber(number, 3)}/>
          <PasscodeTextInput
            ref={this.passcode4}
            onChangeText={number => this.inputNumber(number, 4)} />
          <PasscodeTextInput
            ref={this.passcode5} 
            onChangeText={number => this.inputNumber(number, 5)}/>
          <PasscodeTextInput
            ref={this.passcode6} 
            onChangeText={number => this.inputNumber(number, 6)}/>
        </View>
        <View styles={[styles.centerEverything]}>
            <Button
            style={{ fontSize: 20, color: 'white' }}
            containerStyle={styles.verifyButton}
            onPress={() => this.onVerify()}
            >
            VERIFY
            </Button>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  centerEverything: {
    justifyContent: 'center',
    alignItems: 'center',
    flexDirection: 'row'
    //backgroundColor: 'red'
  },
  container: {
    flex: 1,
    backgroundColor: 'white',
  },
  leftContainer: {
    justifyContent: 'flex-start',
    marginLeft: 20,
    marginRight: 20,
    marginTop: 50
  },
  passcodeContainer: {
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
  },
  firstText: {
      color:"#758D9E",
      marginTop: 12,
      fontSize: 30,
      fontWeight: 'bold',
      textAlign: 'left',
      alignItems: 'flex-start',
      marginLeft: 5,
      marginRight: 5
    },
    secondText: {
      color:"#758D9E",
      marginTop: 18,
      fontSize: 14,
      marginLeft: 10,
      marginRight: 10
    },
    verifyButton: {
      //flex: 0.1,
      justifyContent: 'center',
      alignItems: 'center',
      marginTop:30,
      backgroundColor:'#F64658',
      borderRadius:100,
      borderWidth: 1,
      borderColor: '#fff',
      overflow: 'hidden',
      height: 40,
      //width: 300,
      margin: 30
    },


});

编辑React.forwardRef

之后的我的PasscodeTextInput代码
import React from 'react';
import {
  View,
  Text,
  TextInput,
} from 'react-native';

const PasscodeTextInput = React.forwardRef(({ ref, autoFocus, onSubmitEditing, onChangeText, value}) => {

  const { inputStyle, underlineStyle } = styles;

  return(
    <View>
      <TextInput
        ref={ref}
        autoFocus={autoFocus}
        onSubmitEditing={onSubmitEditing}
        style={[inputStyle]}
        maxLength={1}
        keyboardType="numeric"
        placeholderTextColor="#212121"
        //secureTextEntry={true}
        onChangeText={onChangeText}
        value={value}
      />
      <View style={underlineStyle} />
    </View>
  );
})

const styles = {
  inputStyle: {
    height: 80,
    width: 30,
    fontSize: 50,
    color: '#212121',
    fontSize: 20,
    padding: 5,
    margin: 5,
    marginBottom: 0
  },
  underlineStyle: {
    width: 30,
    height: 4,
    backgroundColor: '#202020',
    marginLeft: 0
  }
}

export { PasscodeTextInput };

2 个答案:

答案 0 :(得分:1)

tl。 博士,将声明更改为
const PasscodeTextInput = ({ ref, autoFocus, onSubmitEditing, onChangeText, value}) => {
收件人:
const PasscodeTextInput = React.forwardRef(({autoFocus, onSubmitEditing, onChangeText, value}, ref) => {
而且不要忘了关闭新括号

说明:
ref不是正常的道具,它会根据您的组件进行处理。使用ref道具时,react内部成员会处理该道具,尝试获取对组件实际实例的引用并将其设置在该实例中,而该道具永远不会到达您的实际组件代码。
由于您的PasswordTextInput组件被定义为一个函数,因此没有实例化,因此您会得到null

您要执行的操作是将ref向下转发到TextInput组件。因此,您明确表示要做出反应,请给您ref道具,以便您可以处理它,但认为适合您。在这种情况下,这会将其转发到TextInput组件。

  

有关更多信息,请参见https://reactjs.org/docs/forwarding-refs.html

答案 1 :(得分:0)

也许您可以尝试在JSX中使用自定义属性。

属性运算符:

let autofocus= {'attribute ': 'value'}

渲染:

   {...autofocus}

例如;

状态组件:

 ......
    <Input
     isAutofocus={true}
     tabindex="1"
    ........
    />

无状态组件:

import React from "react";
const Input = ({isAutofocus,tabindex  .......}) => {
  let autofocus = isAutofocus ? {'autoFocus' : " "}  : ""
  return (
    <div className="form-group">
      <label htmlFor={name}>{label}</label>
      <input
        {...autofocus}
       tabIndex={tabindex}
        ............
      />
    </div>
   )
}
export default Input;