Home > Software engineering >  Problem Keyboard hide after write one char in TextInput (textinput inside Flatlist Header)
Problem Keyboard hide after write one char in TextInput (textinput inside Flatlist Header)

Time:11-06

i spent two days on this problem , the problem is :

when i placed a TextInput inside a Flatlist , the behavior of the TextInput Changed , the Keyboard lose focus after every character writed.

Version React-native : 0.63.2 react : 16.13.1, react-dom : 16.13.1, expo : ~42.0.1,

Steps to reproduce

  • i reated a State Variable called ==> [inputSearch, setInputSearch]
  • i wrote a textinput inside the ListHeaderComponent of Flatlist

---> The problem is : After every Character pressed in Keyboard the Keyboard Hide

State declaration :

const [inputSearch, setInputSearch] = useState(null);

TextInput is inside Flatlist :

    <View style={styles.container}>
    <StatusBar
         backgroundColor="#11131B"
         barStyle="light-content"
    />

    <View style={{width: '100%', flex: 1 , backgroundColor: 'white', marginTop: 5}}>

        <FlatList 
            contentContainerStyle={{alignItems: 'center',paddingHorizontal: 20}}
            keyExtractor={(item) => (Object.keys(item).length === 0) ? "" : item.id.toString()}
            width= {width}
            numColumns={2}
            ListHeaderComponent={() =>
                <View  style={{flexDirection:'column',justifyContent:'space-between'}}>

                   <Text style={{color:Colors.dark1, fontSize:14, marginBottom: 5}}>Search :</Text>
                   <TextInput style={styles.input} value={inputSearch} onChangeText={setInputSearch} placeholder="Username"/>

                </View>
            }
            data={SIMPLE_DATA}
            renderItem={renderItemRow}
        >

        </FlatList>
    </View>

  <View>

CodePudding user response:

I'm going to expand what I wrote on the comment since that was written quickly and not clear enough.

Let's consider the following as a starting point (I stripped off useless information):

function YourComponent() {
  const [inputSearch, setInputSearch] = useState('');

  return (
    <View>
      <StatusBar backgroundColor="#11131B" barStyle="light-content" />

      <View>
        <FlatList
          ListHeaderComponent={() => (
            <>
              <Text>Search :</Text>
              <TextInput
                value={inputSearch}
                onChangeText={setInputSearch}
                placeholder="Username"
              />
            </>
          )}
          data={[]}
          renderItem={() => <View />}
        />
      </View>
    </View>
  );
}

Every time you call setInputSearch the component is rendered again, but this means that the arrow function you are passing inline inside ListHeaderComponent will be called every time and the content will be created again (the keyboard is closed because the input where the focus was on doesn't exist anymore, since it's been replaced by a new one).

How can you solve this? ListHeaderComponent accepts both constructors and ReactElement, so you either pass a ReactElement or create a "standalone" component (no specific meaning, it's just a component on its own, not inside another component).


Here are a couple of solutions:

  1. ReactElement example (notice that the component is passed directly, there is no function in ListHeaderComponent; you can also extract this as another component if you want):
function YourComponent() {
  const [inputSearch, setInputSearch] = useState('');

  return (
    <View>
      <StatusBar backgroundColor="#11131B" barStyle="light-content" />

      <View>
        <FlatList
          ListHeaderComponent={
            <>
              <Text>Search :</Text>
              <TextInput
                value={inputSearch}
                onChangeText={setInputSearch}
                placeholder="Username"
              />
            </>
          }
          data={[]}
          renderItem={() => <View />}
        />
      </View>
    </View>
  );
}
  1. Standalone component (passing the constructor to ListHeaderComponent):
function YourComponent() {
  return (
    <View>
      <StatusBar backgroundColor="#11131B" barStyle="light-content" />

      <View>
        <FlatList
          ListHeaderComponent={ListHeaderComponent}
          data={[]}
          renderItem={() => <View />}
        />
      </View>
    </View>
  );
}

function ListHeaderComponent() {
  const [inputSearch, setInputSearch] = useState('');

  return (
    <>
      <Text>Search :</Text>
      <TextInput
        value={inputSearch}
        onChangeText={setInputSearch}
        placeholder="Username"
      />
    </>
  );
}

but this wouldn't allow you to use the inputSearch value in YourComponent.


I hope this helps clear things out.

  • Related