Home > Mobile >  How to show icon depending on which Pressable is pressed in React Native?
How to show icon depending on which Pressable is pressed in React Native?

Time:11-16

I have a multiple Pressable component. How can I make it that when I clicked on the Motorcycle pressable, the check icon would be shown beside it and if on the Tricycle Pressable, the check icon would be shown beside it and the one on the Motorcycle icon will be gone.

enter image description here

I have tried creating a state but it simultaneously set all icons in place. Here is the code:

  const [checkIcon, setCheckIcon] = useState(false)

<Pressable
            style={({ pressed }) => [{ opacity: pressed ? 0.4 : 1 }, styles.modalField]}
              onPress={() => setCheckIcon(true)}
            >
              <Image source={require("../assets/motorcycle.png")} style={styles.modalFieldImage} />
              <View style={styles.modalFieldVehicleNameContainer}>
                <Text style={styles.modalFieldText}>Motorcycle</Text>
                <Text style={styles.modalFieldTextDescription}>Cheapest option perfect for small-sized items</Text>
                <Text style={styles.modalFieldTextDescription}>Up to 20 kg</Text>
              </View>
              {
                checkIcon === true ? <Icon name="check" type="font-awesome-5" size={hp("3%")} color="#322C6A" style={styles.modalFieldIcon} /> : null
              }
            </Pressable>

            <Pressable
              style={({ pressed }) => [{ opacity: pressed ? 0.4 : 1 }, styles.modalField]}
              onPress={() => setCheckIcon(true)}
            >
              <Image source={require("../assets/tricycle.png")} style={styles.modalFieldImage} />
              <View style={styles.modalFieldVehicleNameContainer}>
                <Text style={styles.modalFieldText}>Tricycle</Text>
                <Text style={styles.modalFieldTextDescription}>Perfect for multiple medium-sized items</Text>
                <Text style={styles.modalFieldTextDescription}>Up to 70 kg</Text>
              </View>
              {
                checkIcon === true ? <Icon name="check" type="font-awesome-5" size={hp("3%")} color="#322C6A" style={styles.modalFieldIcon} /> : null
              }
            </Pressable>

            <Pressable
              style={({ pressed }) => [{ opacity: pressed ? 0.4 : 1 }, styles.modalField]}
              onPress={() => setCheckIcon(true)}
            >
              <Image source={require("../assets/sedan.png")} style={styles.modalFieldImage} />
              <View style={styles.modalFieldVehicleNameContainer}>
                <Text style={styles.modalFieldText}>Sedan Car</Text>
                <Text style={styles.modalFieldTextDescription}>Good for cakes and multiple small to medium-sized items</Text>
                <Text style={styles.modalFieldTextDescription}>Up to 200 kg</Text>
              </View>
              {
                checkIcon === true ? <Icon name="check" type="font-awesome-5" size={hp("3%")} color="#322C6A" style={styles.modalFieldIcon} /> : null
              }
            </Pressable>

CodePudding user response:

Here is an simple example, using a index state to log down which item is selected by user.

Since your list can be generated dynamically, so you may use an array to store all the parameters for rendering and use map() to render one by one.

const [optionArray, setOptionArray] = useState([
    {
      title: "Motorcycle",
      desc1: "Cheapest option perfect for small-sized items",
      desc2: "Up to 20 kg",
      img: "../assets/motorcycle.png",
    },
    {
      title: "Tricycle",
      desc1: "Perfect for multiple medium-sized items",
      desc2: "Up to 70 kg",
      img: "../assets/tricycle.png"
    },
    {
      title: "Sedan Car",
      desc1: "Good for cakes and multiple small to medium-sized items",
      desc2: "Up to 200 kg",
      img: "../assets/sedan.png",
    }
  ]);
  const [selectedIndex, setSelectedIndex] = useState(-1);   //Nothing is selected with initial render

  const ListItem = ({option, index}) =>{
    return(
      <Pressable
        style={({ pressed }) => [{ opacity: pressed ? 0.4 : 1 }, styles.modalField]}
        onPress={() => setSelectedIndex(index)}
      >
        <Image source={option.img} style={styles.modalFieldImage} />
        <View style={styles.modalFieldVehicleNameContainer}>
          <Text style={styles.modalFieldText}>{option.title}</Text>
          <Text style={styles.modalFieldTextDescription}>{option.desc1}</Text>
          <Text style={styles.modalFieldTextDescription}>{option.desc2}</Text>
        </View>
        {
          index === selectedIndex && <Icon name="check" type="font-awesome-5" size={hp("3%")} color="#322C6A" style={styles.modalFieldIcon} />
        }
      </Pressable>
    )
  }

  return(
    <View>
      {
        optionArray.map((option, index) => 
          <ListItem option={option} index={index} />
        )
      }
    </View>
  )

Also answer by Hardik prajapati is another solution too. That method will not affect the result when the data list is sorted in runtime. But large object modification will trigger re-render for components which may lead to performance issue in some case.

Therefore, you can select different approach for your case.

CodePudding user response:

create Vehicle item array like vehicle:[ image:'put your imageUrl', name:'', description:'', clickStatus:true ]

then use map method to display all array item and when you click on any item update your array with clickStatus key pressable item true and other two item false and display Check Icon based on true or false

  • Related