Full disclaimer upfront for this one - I've been working with react native for around a week or two, and I suspect that I've encountered this issue without fully understanding why!
Issue: On each keystroke within a TextInput field, the keyboard closes automatically and only records the first keystroke.
Situation: I am using a prefefined array as the default for useState. The TextInput fields are called using .map() based on the current state. The onChangeText() updates the sate to capture changes to the array. The state is updated with each keystroke.
Things Tried:
- Adding/removing Key to different components used in .map()
- Adding keyboardShouldPersistTaps='handled' to the ScrollView that the .map() is called in, including all other variations avaialble
Does anyone know what is causing the keyboard to close on each keystroke, and how I can prevent this from happening whilst continuing to capture changes to the TextInput fields in the main state?
Snippet below of the code I'm working on (I've removed some of the unrelated detail):
import React, { useState } from 'react';
import {
View,
Text,
Button,
TextInput,
SectionList,
SafeAreaView,
TouchableOpacity,
ScrollView,
Modal,
} from 'react-native';
import { Picker} from '@react-native-community/picker';
//import custom components
import { styles, Break } from './MasterStyles';
import { inputData, ingredients } from './inputData';
function addNewLoaf() {
const [ingredientsList, setIngredientsList] = useState(ingredients);
const [selectedLoaf, setSelectedLoaf] = useState('Regular Loaf');
const [flourModalVisibility, setFlourModalVisibility] = useState(false);
const [newLoaf, setNewLoaf] = useState('');
function IngredientsRecorder() {
return (
<View style={styles.ingredientsContainer}>
<View style={{flexDirection: 'column'}}>
<View>
<Text style={styles.metricTitle}>
Volume of Ingredients:
</Text>
</View>
{
ingredientsList.map(e => {
if(e.isVisible && e.ingredient){
return (
<View style={{flexDirection: 'row', alignItems: 'center'}} key={e.id}>
<View style={{flex:2}}>
<Text style={styles.metricText}>{e.name}:</Text>
</View>
<View style={{flex:3}}>
<TextInput
placeholder='amount'
style={styles.inputText}
keyboardType='number-pad'
value={e.amount}
onChangeText={value => ingredientsAmountHandler(value, e.id)}
/>
</View>
<View style={{flex:1}}>
<Text style={styles.ingredientsText}>{e.units}</Text>
</View>
</View>
)
}
})
}
</View>
</View>
)
}
const ingredientsAmountHandler = (text, id) => {
// setAmount(enteredText);
let newArray = [...ingredientsList]
let index = newArray.findIndex(element => element.id === id)
newArray[index].amount = text
setIngredientsList(newArray)
}
return (
<SafeAreaView style={styles.container}>
<View style={styles.page}>
<Text style={styles.titleText}>Add a New Loaf</Text>
<Break />
<View style={{flexDirection: 'row'}}>
<TextInput
placeholder='What would you like to call your loaf?'
style={styles.inputText}
onChangeText={loafNameInputHandler}
value={newLoaf}
/>
<Button title='Create Loaf' color='#342e29' onPress={addNewLoafHandler} />
</View>
<Break />
<ScrollView styles={styles.page} keyboardShouldPersistTaps='handled'>
<LoafSelector />
<FlourSelector />
<IngredientsRecorder />
</ScrollView>
</View>
<Break />
</SafeAreaView>
);
}
export { addNewLoaf }