1

I'm trying to do a 6 digits verification code form (I know there is actually a package to do but I want it differently).

So I've done it like so:

const RegisterStep2 = (props) => {
  const [digits, setDigits] = useState([]);
  const textInputRefs = [];

  const isNumeric = (str) => {
    if (typeof str == 'number') return true;
    if (typeof str != 'string') return false;
    return !isNaN(str) && !isNaN(parseFloat(str));
  };

handleForm = (index, value) => {
    let digitsArray = digits;
    let trueIndex = index;
    for (let i = index - 1; i >= 0; i--) {
      if (!isNumeric(digits[i])) {
        trueIndex = i;
      }
    }
    textInputRefs[trueIndex].focus();
    index = trueIndex;

    if (!isNumeric(digits[index])) {
      if (value.key == 'Backspace' && textInputRefs[index - 1] != undefined) {
        textInputRefs[index - 1].focus();
      }
      if (isNumeric(value.key)) {
        digitsArray[index] = value.key;
      } else {
      }
    } else {
      if (value.key == 'Backspace') {
        digitsArray[index] = '';
      } else if (isNumeric(value.key)) {
        digitsArray[index] = value.key;
      }
    }
    setDigits(digitsArray);
    if (isNumeric(digits[index]) && textInputRefs[index + 1]) {
      textInputRefs[index + 1].focus();
    } else if(index == textInputRefs.length) {
      submitForm();
    }

return (
  ...
  <TextInput
    ref={(input) => {
      textInputRefs[1] = input;
    }}
    style={style.formDigit}
    keyboardType={'numeric'}
    maxLength={1}
    underlineColorAndroid="transparent"
    autoCapitalize="none"
    value={digits[1]}
    onKeyPress={({ nativeEvent }) => {
      handleForm(1, nativeEvent);
    }}
    blurOnSubmit={false}
  />
  ... //The same input x3 times with corresponding index
  <TextInput
    ref={(input) => {
      textInputRefs[5] = input;
    }}
    style={style.formDigit}
    keyboardType={'numeric'}
    maxLength={1}
    underlineColorAndroid="transparent"
    autoCapitalize="none"
    value={digits[5]}
    onKeyPress={({ nativeEvent }) => {
      handleForm(5, nativeEvent);
    }}
    blurOnSubmit={false}
  />
  ...
);

Everything is working pretty well but the value of the input doesn't update in the way I want, when the user presses a key that is not handled by the handleForm (NaN), the input doesn't display what it that should (digits[index]) but it displays the pressed key(not the value it is bind to).

digits value result as expected

digits render not as expected

digits render as expected

Same for when the user is writing in a textInput that is not the first empty one, the input that should be written should be the first empty one:

digits value as expected

digits render not as expected

digits render as expected

So I wonder why the value that is displayed isn't the real state value, did I broke something, why the pipe between the state and the input seems broken. Even when the state gets updated (so the view is re-rendered), the input doesn't display his true value.

Pejman Kheyri
  • 4,044
  • 9
  • 32
  • 39
eJanuel
  • 13
  • 2

0 Answers0