How to update value inside object from inputText - react-native

Sorry guys i'am still learning react native and i want update value of each qty(quantity) item from input, so i have this state,
this.state={
selectedObject={
otherAttributes:'',
items:[
{name:'a',qty:''},
{name:'b',qty:''},
],
},
}
then i have this function to render the TextInput,
renderPage(){
return this.state.selectedObject.items.map(item ,i)=>
<View style={{margin:15}}>
<Text>Name: {item.name}</Text>
<TextInput style={styles.input} keyboardType='numeric' maxLength={10}
value={?}
onChangeText={?}
}}/>
</View>
)
}
and i dont know what to do inside the value and onchangeText,
This is what i tried, in the TextInput
renderPage(){
const itemqty = this.state.selectedObject.items;
return itemqty.map((item,i)=>
<View style={{margin:15}}>
<Text>Name: {item.name}</Text>
<TextInput style={styles.input} keyboardType='numeric'
value={itemqty[i].qty}
onChangeText={(qty)=>{
this.setState({items[i].qty: qty});
}}/>
</View>
)
}
after trying this i'am aware that value can't have '[i]' aswell as in the setState. Because i was trying so that the value qty will go to the respected items qty as well when setState it.
So what i expect is i can change the value of the quantity of the items from the input that are available in this case there are 2, but later on it can be 3,4,5,6 items with qty in each one and set it to the respected state.
Thank you

You have to pass the modified state properties to setState.
PS: I had to update in order to reflect Junius L. comment about not changing component state.
renderPage(){
const itemqty = this.state.selectedObject.items;
return itemqty.map((item,i)=>
<View style={{margin:15}}>
<Text>Name: {item.name}</Text>
<TextInput style={styles.input} keyboardType='numeric'
value={item.qty}
onChangeText={(qty)=>{
let newSelectedObject = {...this.state.selectedObject};
newSelectedObject.items = [...newSelectedObject.items];
newSelectedObject.items[i] = {...newSelectedObject.items[i], qty};
this.setState({selectedObject: newSelectedObject});
}}/>
</View>
)
}
Also, selectedObject is a state property. So the correct is
this.state={
selectedObject:{
otherAttributes:'',
items:[
{name:'a',qty:''},
{name:'b',qty:''},
],
},
}

Try to avoid state mutation, by not updating the array directly.
hanldeChange = (value, index) => {
const items = [
...this.state.selectedObject.items.slice(0, index),
Object.assign({}, this.state.selectedObject.items[index], { qty: value }),
...this.state.selectedObject.items.slice(index + 1),
];
this.setState(prevState => ({
selectedObject: {
...prevState.selectedObject,
items: items,
},
}));
};
In your input do
<TextInput
style={styles.input}
keyboardType="numeric"
value={this.state.selectedObject.items[i].qty}
onChangeText={qty => this.hanldeChange(qty, i)}
/>

Related

Is there a way to set a state with textinput when onChangeText is already in use?

Im trying to set a state with the values from a textinput (which is a reusable component), Im using onChangeText to setFieldValue (useFormikContext()), I also want to set a state which will be sending to the Parent component. I tried using onChange but noticed it saves the text without the last word/number, for instance if I type 0123456789, the setFieldValue gets 0123456789, but the other one (with onChange) gets only 012345678 (without 9).
Here is the code:
function AppFormField({ name, width, childToParent, ...otherProps }) {
const { setFieldTouched, setFieldValue, errors, touched, values } =
useFormikContext();
return (
<>
<TextInput
onBlur={() => setFieldTouched(name)}
onChangeText={(text) => setFieldValue(name, text)}
onChange={() => childToParent(bn)}
value={values[name]}
width={width}
{...otherProps}
/>
<ErrorMessage error={errors[name]} visible={touched[name]} />
</>
);
}
Parent Component:
...
const [bn, setBN] = useState("");
const childToParent = (childdata) => {
setBN(childdata);
console.log(childdata);
};
console.log("bn");
console.log(bn);
...
return (
...
<UppFormField
keyboardType="numeric"
autoCorrect={false}
// icon="bank"
name="acct_number"
placeholder="Account Number"
style={{ paddingRight: 50 }}
childToParent={childToParent}
/>
...
)
Make a middle function called
const onTextChange = (text) => {
setFieldValue(text)
parentFunction(text)
}
then TextInput takes has
onChangeText={onTextChange}

How to Get Multiple TextInput Values in single variable in React-Native?

How to get values from multiple TextInput fields coming from array passing by map function to single variable by entering text in them? When i try to enter text in second TextInput it replaces the value which i stored from first TextInput.
Secondly instead of this, if i use push() function, it doesn't give desired output. What I exactly want is that to get the values of these three InputText and to store in single variable using single OnChangeEvent (as I am using Map() function).
Below is the sample of code on which i am working in React-Native.
this.state={
checkboxAttCollection:[{"Id": 10, "AttibuteCollectionName": "PowerTest"}, {"Id": 22, "AttibuteCollectionName": "36W"}, {"Id": 23, "AttibuteCollectionName": "Test123"}],
getInputText:'',
getInputvariables:[],
onChangeTextComp=(TextValue,index)=>{
this.state.getInputText=TextValue
console.log("******",this.state.getInputvariables)
this.state.getInputvariables.push(this.state.getInputText)
console.log("******",this.state.getInputvariables)
{this.state.checkboxAttCollection.map((item, i) =>
return (<View key={item.AttibuteCollectionId} style={{ flexDirection: 'row',}}>
<TextInput style={{height:hp('5%'),width:wp('60%'),backgroundColor:'red',borderBottomWidth:2,paddingVertical:0}}
onChangeText={(text)=>this.onChangeTextComp(text,i)}
MultiInputText={true}/>
{/* </View> */}
</View>)
})}
Try this way
this.state={
......
inputVlaues: []
}
onChangeTextComp=(value,index)=>{
const inputData = [...this.state.inputVlaues];
inputData[index] = value;
this.setState(inputVlaues: inputData);
}
{this.state.checkboxAttCollection.map((item, i) =>
return
(<View key={item.AttibuteCollectionId} style={{ flexDirection: 'row',}}>
<TextInput
onChangeText={(text)=>this.onChangeTextComp(text,i)}
......
value={this.state.inputVlaues[i] || ""}
/>
</View>)
})}
as an option you can generate event handlers dynamically
const [form, setForm] = useState({})
const createHandler = (fieldName) => {
return (newFieldValue) => {
setForm((oldValue) => {
return {
...oldValue,
[fieldName]: newFieldValue
}
})
}
}
return (
<>
<TextInput onChange={createHandler('name')} />
<TextInput onChange={createHandler('surname')} />
</>
)

FlatList not rendering style dynamically

I'm currently struggling in making my FlatList applying the changes I do to it. What I am wanting right now is that when I click an item in my flatlist, that it highlights in a certain color. I followed an approach done by a guy but I am having the problem that to me is not working the update once I click.
I can see through console that all I am doing performs a modification but I think that I am missing some point with extraData parameter since it is not re-rendering with the backgroundColor that I would like to apply.
The code I have is as following, I know that the style I am applying is correct since if i substitute in the map styles.list per styles.selected, everything gets the background I would like to be applied to the elements I click.
So summarizing, the issue I think I have is that the flatlist is not re-rendering so it doesn't show the modifications I perform on it. Any idea of what I am doing wrong? Any tip?
render() {
const { students, studentsDataSource, loading, userProfile } = this.props.navigation.state.params.store;
this.state.dataSource = studentsDataSource._dataBlob.s1.map(item => {
item.isSelect = false;
item.selectedClass = styles.list;
return item;
})
const itemNumber = this.state.dataSource.filter(item => item.isSelect).length;
return (
<View style={styles.container}>
<Item rounded style={styles.searchBar}>
<Input placeholder='Group Name'/>
</Item>
<FlatList
style={{
flex: 1,
width: "100%",
}}
data={this.state.dataSource}
ItemSeparatorComponent={this.FlatListItemSeparator}
renderItem={ ({ item }) => (
<ListItem avatar style={[styles.list, item.selectedClass]}
onPress={() => this.selectItem(item)}>
<Left>
{!item.voteCount && <Avatar unseen={true} /> }
{!!item.voteCount > 0 && <Avatar />}
</Left>
<Body>
<Text>{item.name}</Text>
<Text note>{item.group}</Text>
</Body>
</ListItem>
)
}
listKey={item => item.key}
extraData={this.state}
/>
</View>
);
}
Here we can find the state and SelectItem functions:
constructor(props) {
super(props)
this.state = {
dataSource : [],
}
}
//FlatListItemSeparator = () => <View style={styles.line} />;
selectItem = data => {
//{console.log("inside SelectItem=", data)}
data.isSelect = !data.isSelect;
data.selectedClass = data.isSelect? styles.selected: styles.list;
const index = this.state.dataSource.findIndex( item => data.key === item.key);
this.state.dataSource[index] = data;
this.setState({
dataSource: this.state.dataSource,
});
console.log("This state has the changes:=",this.state.dataSource)
};
Well the main issue was that I was not using the .setState and instead I was doing assignations which killed the listeners.

react-native-elements checkbox update value

I have the following code and for some reason the checkbox is not updated when I click on them. Does anyone know what might be the problem? I am using CheckBox from react-native-elements. The checked property is based on whether a value exists in a set. The onpress function updates the state variable and I am able to get the correct values from the state variable. Thanks!
constructor(props) {
super(props);
this.state = {
interests: new Set(),
brands: new Set(),
medicalCondition: new Set(),
errorMessage: '',
loading: false
}
}
onPressHandler = (event, value, keyName) => {
let tempCheckedValues = new Set(this.state[keyName]);
tempCheckedValues.has(value) ? tempCheckedValues.delete(value) : tempCheckedValues.add(value);
console.log(tempCheckedValues);
this.setState({[keyName] : tempCheckedValues});
}
renderCheckboxGroup = (checkboxList, keyName) => {
return checkboxList.map((value, index) => {
return (
<CheckBox
key={index}
title={value}
onPress={(event) => this.onPressHandler(event, value, keyName)}
checked={this.state[keyName].has(value.toLowerCase())}
/>
)
})
}
render() {
const interestsConst = ["Tennis", "Golf", "Shopping", "Movie", "Hiking", "Reading", "Diving", "Investing"];
const brandsConst = ["Chanel", "Louis Vuitton", "H&M", "ZARA", "Hermes", "Gucci", "Cartier", "Burberry", "Nike", "Adidas", "Lululemon", "Athleta"];
const medicalConditionConst = ["Hypertension", "Hyperlipidemia", "Diabetes", "Back pain", "Anxiety", "Asthma", "Cancer", "Depression", "Shingles"];
return (
<View style={styles.container}>
<ScrollView>
<View style={styles.cardGroup}>
<Card title='Interests'>
{this.renderCheckboxGroup(interestsConst, 'interests')}
</Card>
</View>
<View style={styles.cardGroup}>
<Card title='Brands'>
{this.renderCheckboxGroup(brandsConst, 'brands')}
</Card>
</View>
<View style={styles.cardGroup}>
<Card title='Medical Conditions'>
{this.renderCheckboxGroup(medicalConditionConst, 'medicalCondition')}
</Card>
</View>
</ScrollView>
</View>
)
}
}

How do you get nativeID for react-native InputAccessoryView

I am following the documentation on InputAccessoryView here: https://facebook.github.io/react-native/blog/2018/03/22/building-input-accessory-view-for-react-native.html
with code:
export default class Debug extends Component {
constructor(props) {
super(props);
this.state = {text: 'Hello world from debug'};
}
render() {
const inputAccessoryViewID = "uniqueID";
const accesory = (
<InputAccessoryView nativeID={inputAccessoryViewID}>
<Button
onPress={() => this.setState({text: 'You didnt enter the magic word'})}
title="Reset Text"
/>
</InputAccessoryView>
)
return (
<View>
<ScrollView keyboardDismissMode="interactive">
<TextInput
style={{
padding: 10,
paddingTop: 50,
}}
inputAccessoryViewID={inputAccessoryViewID}
onChangeText={text => this.setState({text})}
value={this.state.text}
/>
</ScrollView>
{accesory}
</View>
);
}
}
But the docs do not explain where I can get this id uniqueID. Is it something I can find in xcode?
InputAccessoryView is expecting a unique id for nativeID property to match with a TextInput that has the same unique id set on inputAccessoryViewID property. This way it knows to activate on that input. This way you can have different InputAccessoryViews for different TextInputs.
nativeID
An ID which is used to associate this InputAccessoryView to specified
TextInput(s).
So that uniqueID is some string that is unique which you can set to anything yourself to match with the TextInput.