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:
- 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>
);
}
- 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.