javascripthtmlreactjsreact-native

How to show placeholder in an OTP Input only when box Is empty and unfocused?


I’m working on an OTP input screen in React Native where I need to show a placeholder () inside the input fields under the following conditions:

  1. When a box is focused, the placeholder should not be visible.
  2. After clearing the value in any box, the placeholder () should appear only if the box is empty, even if the box is not focused.

Current Code:

Here’s the code I’m using:

<View style={styles.otpContainer}>
  {[...new Array(4)].map((_, index) => (
    <TextInput
      ref={ref => {
        inputs.current[index] = ref;
      }}
      key={index}
      style={[
        styles.otpInput,
        focusedIndex === index && { borderColor: tertiary },
        invalidOtp && { borderColor: error },
      ]}
      keyboardType="number-pad"
      maxLength={1}
      selectTextOnFocus
      contextMenuHidden
      testID={`OTPInput-${index}`}
      onChangeText={text => handleChangeText(text, index)}
      onKeyPress={e => handleKeyPress(e, index)}
      value={otpValues[index]}
      placeholder={otpValues[index] === '' && focusedIndex !== index ? '•' : ''}
      placeholderTextColor={secondary}
      onFocus={() => setFocusedIndex(index)} 
      onBlur={() => setFocusedIndex(null)} 
    />
  ))}
</View>

Problem:

Expected Behavior:


Solution

  • I think the problem was with the check on placeholder you should be checking for focused index only, because once the input has some value it automatically disables the placeholder.

    I simplified your code a little for me to solve the problem, now it is working, just tweak the placeholder check as below and the code should work.

    const [focusedIndex, setFocusedIndex] = React.useState(-1);
    
    <View>
      {[...new Array(4)].map((_, index) => (
        <TextInput
          key={index}
          keyboardType="number-pad"
          maxLength={1}
          selectTextOnFocus
          contextMenuHidden
          testID={`OTPInput-${index}`}
          placeholder={focusedIndex !== index ? '•' : ''}
          onFocus={() => setFocusedIndex(index)} 
          onBlur={() => setFocusedIndex(-1)} 
        />
      ))}
    </View>