Search code examples
react-nativeonpress

How to update the attribute of an item of a FlatList?


I have programmed an Android app which is consists of a TextInput, a Button and a FlatList. With each name That is written in the TextInput, there will be an item in the flat list. The Item title will be the TextInput content and there will be two buttons and a text right beside the list item. A button is for increasing the number that Text displays by 1 and the other one is for decreasing. here is my code:

import React, {Component} from 'react';
import {
  View,
  Text,
  TextInput,
  FlatList,
  TouchableOpacity,

} from 'react-native';
import { ListItem, SearchBar} from 'react-native-elements';


class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      task: "",
      task_array: [],


    };
  }

  ChangeText = (some_task) => {
    this.setState({task: some_task});
  };
  pushAdd = () => {
    let contact = {
      name: this.state.task,
      counter: 0,
    };
    this.setState({task_array: [...this.state.task_array, contact]});
  };








  renderListItem = ({item}) => {
   return(
     <View style={{flexDirection: 'row'}}>
     <ListItem title={item.name} style={{width:'75%', marginLeft:20}}></ListItem>
     <View style={{flexDirection:'row'}}>
         <TouchableOpacity style={{ backgroundColor: 'blueviolet', height: 20, width: 20, borderRadius: 50}} onPress={()=> item={name:item.name, counter:item.counter + 1}}><Text>+</Text></TouchableOpacity>
         <Text>{item.counter}</Text>
  //main problem       <TouchableOpacity style={{ backgroundColor: 'blueviolet', height: 20, width: 20, borderRadius: 50 }} onPress={() => item = { name: item.name, counter: item.counter - 1 }}><Text>-</Text></TouchableOpacity>

     </View>

     </View>

   );
  };


render() {
  return(
    <View style={{ backgroundColor: 'mediumturquoise', width:'100%', height:'100%'}}>
    <FlatList 
      data = {this.state.task_array}
      renderItem = {this.renderListItem}
      keyExtractor = {(item) => item.name}>
    </FlatList>
    <View style = {{flexDirection : 'row', alignContent:'center', alignItems:'center'}}>
        <TextInput onChangeText={this.ChangeText} style={{ backgroundColor: 'burlywood', height:50, width:'75%', borderRadius:30, marginBottom:20, marginLeft:20, marginRight:20}}></TextInput>
        <TouchableOpacity style={{ backgroundColor: 'chocolate', height:40, width:50, borderRadius:10, marginBottom:20}} onPress={this.pushAdd}></TouchableOpacity>
    </View>
    </View>
  );
  }
};

export default App;

I have pointed the problematic line with the comment 'main problem'. the increase and decrease button don't do their job and when I press them in the app, the number in the text remains unchanged. What change should I perform on the onPress method of my increase and decrease button to get them to work?


Solution

  • in React, you you can't manipulate data directly (like you are doing in your +/- buttons onPress methods). This will have no effect, instead, you need to change state appropriately by using setState

    the fastest fix to this would be changing

    // this
    renderListItem = ({item}) => {
    // to this
    renderListItem = ({item, index}) => {
    

    to know the index of rendered item. Then, change the onPress method of your increment/decrement buttons inside these item to utilize setState instead

    // from this
    onPress={()=> item={name:item.name, counter:item.counter + 1}}
    // to this
    onPress={() =>
              this.setState({
                task_array: this.state.task_array
                  .map((item, itemIndex) =>
                    itemIndex !== index
                      ? item
                      : {
                        ...item,
                        counter: item.counter + 1
                      })
              })}
    

    What happens here is we create a new task_array from the old one using .map() method of array, leaving every element untouched except the one element that was clicked - which we define by comparing indexes. In this case we increment it's counter and assign new value to task_array by using this.setState